xref: /plan9-contrib/sys/src/9k/boot/local.c (revision 532111f7bd696f808abc982252c7e1b4786fc4a7)
19ef1f84bSDavid du Colombier #include <u.h>
29ef1f84bSDavid du Colombier #include <libc.h>
39ef1f84bSDavid du Colombier #include <../boot/boot.h>
49ef1f84bSDavid du Colombier 
59ef1f84bSDavid du Colombier static char diskname[64];
69ef1f84bSDavid du Colombier static char *disk;
79ef1f84bSDavid du Colombier static char **args;
89ef1f84bSDavid du Colombier 
99ef1f84bSDavid du Colombier void
configlocal(Method * mp)109ef1f84bSDavid du Colombier configlocal(Method *mp)
119ef1f84bSDavid du Colombier {
12*532111f7SDavid du Colombier 	char *p, *inibootdisk;
139ef1f84bSDavid du Colombier 	int n;
149ef1f84bSDavid du Colombier 
15*532111f7SDavid du Colombier 	inibootdisk = getenv("bootdisk");
169ef1f84bSDavid du Colombier 	if(*sys == '/' || *sys == '#'){
179ef1f84bSDavid du Colombier 		/*
189ef1f84bSDavid du Colombier 		 *  if the user specifies the disk in the boot cmd or
199ef1f84bSDavid du Colombier 		 * 'root is from' prompt, use it
209ef1f84bSDavid du Colombier 		 */
219ef1f84bSDavid du Colombier 		disk = sys;
229ef1f84bSDavid du Colombier 	} else if(strncmp(argv0, "dksc(0,", 7) == 0){
239ef1f84bSDavid du Colombier 		/*
249ef1f84bSDavid du Colombier 		 *  on many mips arg0 of the boot command specifies the
259ef1f84bSDavid du Colombier 		 *  scsi logical unit number
269ef1f84bSDavid du Colombier 		 */
279ef1f84bSDavid du Colombier 		p = strchr(argv0, ',');
289ef1f84bSDavid du Colombier 		n = strtoul(p+1, 0, 10);
299ef1f84bSDavid du Colombier 		sprint(diskname, "#w%d/sd%dfs", n, n);
309ef1f84bSDavid du Colombier 		disk = diskname;
319ef1f84bSDavid du Colombier 	} else if(mp->arg){
329ef1f84bSDavid du Colombier 		/*
33*532111f7SDavid du Colombier 		 *  a default is optionally supplied when the kernel is made
349ef1f84bSDavid du Colombier 		 */
359ef1f84bSDavid du Colombier 		disk = mp->arg;
36*532111f7SDavid du Colombier 	} else if(inibootdisk != nil && *inibootdisk)
37*532111f7SDavid du Colombier 		/* plan9.ini overrides default from config file */
38*532111f7SDavid du Colombier 		disk = inibootdisk;
39*532111f7SDavid du Colombier 	else if(bootdisk != nil && *bootdisk){
409ef1f84bSDavid du Colombier 		/*
419ef1f84bSDavid du Colombier 		 *  an environment variable from a pc's plan9.ini or
429ef1f84bSDavid du Colombier 		 *  from the mips nvram or generated by the kernel
439ef1f84bSDavid du Colombier 		 *  is the last resort.
449ef1f84bSDavid du Colombier 		 */
459ef1f84bSDavid du Colombier 		disk = bootdisk;
469ef1f84bSDavid du Colombier 	}
479ef1f84bSDavid du Colombier 
489ef1f84bSDavid du Colombier 	/* if we've decided on one, pass it on to all programs */
49*532111f7SDavid du Colombier 	if(disk) {
50*532111f7SDavid du Colombier 		bootdisk = disk;
51*532111f7SDavid du Colombier 		setenv("bootdisk", bootdisk);
52*532111f7SDavid du Colombier 	}
539ef1f84bSDavid du Colombier }
549ef1f84bSDavid du Colombier 
559ef1f84bSDavid du Colombier int
connectlocalkfs(void)569ef1f84bSDavid du Colombier connectlocalkfs(void)
579ef1f84bSDavid du Colombier {
589ef1f84bSDavid du Colombier 	int i, pid, fd, p[2];
599ef1f84bSDavid du Colombier 	char partition[64];
609ef1f84bSDavid du Colombier 	char *dev;
619ef1f84bSDavid du Colombier 	char **arg, **argp;
629ef1f84bSDavid du Colombier 	Dir *d;
639ef1f84bSDavid du Colombier 
649ef1f84bSDavid du Colombier 	if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
659ef1f84bSDavid du Colombier 		return -1;
669ef1f84bSDavid du Colombier 
679ef1f84bSDavid du Colombier 	dev = disk ? disk : bootdisk;
689ef1f84bSDavid du Colombier 	snprint(partition, sizeof partition, "%sfs", dev);
699ef1f84bSDavid du Colombier 	fd = open(partition, OREAD);
709ef1f84bSDavid du Colombier 	if(fd < 0){
719ef1f84bSDavid du Colombier 		strcpy(partition, dev);
729ef1f84bSDavid du Colombier 		fd = open(partition, OREAD);
739ef1f84bSDavid du Colombier 		if(fd < 0)
749ef1f84bSDavid du Colombier 			return -1;
759ef1f84bSDavid du Colombier 	}
769ef1f84bSDavid du Colombier 	/*
779ef1f84bSDavid du Colombier 	 * can't do this check -- might be some other server posing as kfs.
789ef1f84bSDavid du Colombier 	 *
799ef1f84bSDavid du Colombier 	memset(buf, 0, sizeof buf);
809ef1f84bSDavid du Colombier 	pread(fd, buf, 512, 0);
819ef1f84bSDavid du Colombier 	close(fd);
829ef1f84bSDavid du Colombier 	if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
839ef1f84bSDavid du Colombier 		if(strstr(partition, "/fs"))
849ef1f84bSDavid du Colombier 			print("no kfs file system found on %s\n", partition);
859ef1f84bSDavid du Colombier 		return -1;
869ef1f84bSDavid du Colombier 	}
879ef1f84bSDavid du Colombier 	 *
889ef1f84bSDavid du Colombier 	 */
899ef1f84bSDavid du Colombier 	d = dirfstat(fd);
909ef1f84bSDavid du Colombier 	close(fd);
919ef1f84bSDavid du Colombier 	if(d == nil)
929ef1f84bSDavid du Colombier 		return -1;
939ef1f84bSDavid du Colombier 	if(d->mode&DMDIR){
949ef1f84bSDavid du Colombier 		free(d);
959ef1f84bSDavid du Colombier 		return -1;
969ef1f84bSDavid du Colombier 	}
979ef1f84bSDavid du Colombier 	free(d);
989ef1f84bSDavid du Colombier 
999ef1f84bSDavid du Colombier 	print("kfs...");
1009ef1f84bSDavid du Colombier 	if(pipe(p)<0)
1019ef1f84bSDavid du Colombier 		fatal("pipe");
1029ef1f84bSDavid du Colombier 	switch(pid = fork()){
1039ef1f84bSDavid du Colombier 	case -1:
1049ef1f84bSDavid du Colombier 		fatal("fork");
1059ef1f84bSDavid du Colombier 	case 0:
1069ef1f84bSDavid du Colombier 		arg = malloc((bargc+5)*sizeof(char*));
1079ef1f84bSDavid du Colombier 		argp = arg;
1089ef1f84bSDavid du Colombier 		*argp++ = "kfs";
1099ef1f84bSDavid du Colombier 		*argp++ = "-f";
1109ef1f84bSDavid du Colombier 		*argp++ = partition;
1119ef1f84bSDavid du Colombier 		*argp++ = "-s";
1129ef1f84bSDavid du Colombier 		for(i=1; i<bargc; i++)
1139ef1f84bSDavid du Colombier 			*argp++ = bargv[i];
1149ef1f84bSDavid du Colombier 		*argp = 0;
1159ef1f84bSDavid du Colombier 
1169ef1f84bSDavid du Colombier 		dup(p[0], 0);
1179ef1f84bSDavid du Colombier 		dup(p[1], 1);
1189ef1f84bSDavid du Colombier 		close(p[0]);
1199ef1f84bSDavid du Colombier 		close(p[1]);
1209ef1f84bSDavid du Colombier 		exec("/boot/kfs", arg);
1219ef1f84bSDavid du Colombier 		fatal("can't exec kfs");
1229ef1f84bSDavid du Colombier 	default:
1239ef1f84bSDavid du Colombier 		break;
1249ef1f84bSDavid du Colombier 	}
1259ef1f84bSDavid du Colombier 	for(;;){
1269ef1f84bSDavid du Colombier 		if((i = waitpid()) == -1)
1279ef1f84bSDavid du Colombier 			fatal("waitpid for kfs failed");
1289ef1f84bSDavid du Colombier 		if(i == pid)
1299ef1f84bSDavid du Colombier 			break;
1309ef1f84bSDavid du Colombier 	}
1319ef1f84bSDavid du Colombier 
1329ef1f84bSDavid du Colombier 	close(p[1]);
1339ef1f84bSDavid du Colombier 	return p[0];
1349ef1f84bSDavid du Colombier }
1359ef1f84bSDavid du Colombier 
1369ef1f84bSDavid du Colombier void
runv(char ** argv)137*532111f7SDavid du Colombier runv(char **argv)
1389ef1f84bSDavid du Colombier {
1399ef1f84bSDavid du Colombier 	int i, pid;
1409ef1f84bSDavid du Colombier 
1419ef1f84bSDavid du Colombier 	switch(pid = fork()){
1429ef1f84bSDavid du Colombier 	case -1:
1439ef1f84bSDavid du Colombier 		fatal("fork");
1449ef1f84bSDavid du Colombier 	case 0:
145*532111f7SDavid du Colombier 		exec(argv[0], argv);
146*532111f7SDavid du Colombier 		fatal(smprint("can't exec %s: %r", argv[0]));
1479ef1f84bSDavid du Colombier 	default:
1489ef1f84bSDavid du Colombier 		while ((i = waitpid()) != pid && i != -1)
1499ef1f84bSDavid du Colombier 			;
1509ef1f84bSDavid du Colombier 		if(i == -1)
151*532111f7SDavid du Colombier 			fatal(smprint("wait failed running %s", argv[0]));
1529ef1f84bSDavid du Colombier 	}
1539ef1f84bSDavid du Colombier }
1549ef1f84bSDavid du Colombier 
155*532111f7SDavid du Colombier void
run(char * file,...)156*532111f7SDavid du Colombier run(char *file, ...)
157*532111f7SDavid du Colombier {
158*532111f7SDavid du Colombier 	runv(&file);
159*532111f7SDavid du Colombier }
160*532111f7SDavid du Colombier 
1619ef1f84bSDavid du Colombier static int
print1(int fd,char * s)1629ef1f84bSDavid du Colombier print1(int fd, char *s)
1639ef1f84bSDavid du Colombier {
1649ef1f84bSDavid du Colombier 	return write(fd, s, strlen(s));
1659ef1f84bSDavid du Colombier }
1669ef1f84bSDavid du Colombier 
1679ef1f84bSDavid du Colombier void
configloopback(void)1689ef1f84bSDavid du Colombier configloopback(void)
1699ef1f84bSDavid du Colombier {
1709ef1f84bSDavid du Colombier 	int fd;
1719ef1f84bSDavid du Colombier 
1729ef1f84bSDavid du Colombier 	if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
1739ef1f84bSDavid du Colombier 		bind("#I", "/net", MAFTER);
1749ef1f84bSDavid du Colombier 		if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
1759ef1f84bSDavid du Colombier 			fatal("open /net/ipifc/clone for loopback");
1769ef1f84bSDavid du Colombier 	}
1779ef1f84bSDavid du Colombier 	if(print1(fd, "bind loopback /dev/null") < 0
1789ef1f84bSDavid du Colombier 	|| print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
1799ef1f84bSDavid du Colombier 		fatal("write /net/ipifc/clone for loopback");
1809ef1f84bSDavid du Colombier }
1819ef1f84bSDavid du Colombier 
1829ef1f84bSDavid du Colombier int
connectlocalfossil(void)1839ef1f84bSDavid du Colombier connectlocalfossil(void)
1849ef1f84bSDavid du Colombier {
1859ef1f84bSDavid du Colombier 	int fd;
1869ef1f84bSDavid du Colombier 	char *venti, *f[32], *p;
1879ef1f84bSDavid du Colombier 	int nf;
1889ef1f84bSDavid du Colombier 	char partition[128], buf[512];
1899ef1f84bSDavid du Colombier 	char *dev;
1909ef1f84bSDavid du Colombier 
1919ef1f84bSDavid du Colombier 	if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
1929ef1f84bSDavid du Colombier 		return -1;
1939ef1f84bSDavid du Colombier 
1949ef1f84bSDavid du Colombier 	/* look for fossil partition */
1959ef1f84bSDavid du Colombier 	dev = disk ? disk : bootdisk;
1969ef1f84bSDavid du Colombier 	snprint(partition, sizeof partition, "%sfossil", dev);
1979ef1f84bSDavid du Colombier 	fd = open(partition, OREAD);
1989ef1f84bSDavid du Colombier 	if(fd < 0){
1999ef1f84bSDavid du Colombier 		strcpy(partition, dev);
2009ef1f84bSDavid du Colombier 		fd = open(partition, OREAD);
2019ef1f84bSDavid du Colombier 		if(fd < 0)
2029ef1f84bSDavid du Colombier 			return -1;
2039ef1f84bSDavid du Colombier 	}
2049ef1f84bSDavid du Colombier 	memset(buf, 0, sizeof buf);
2059ef1f84bSDavid du Colombier 	pread(fd, buf, 512, 127*1024);
2069ef1f84bSDavid du Colombier 	close(fd);
2079ef1f84bSDavid du Colombier 	if(memcmp(buf, "fossil config\n", 14) != 0){
2089ef1f84bSDavid du Colombier 		if(strstr(partition, "/fossil"))
2099ef1f84bSDavid du Colombier 			print("no fossil config found on %s\n", partition);
2109ef1f84bSDavid du Colombier 		return -1;
2119ef1f84bSDavid du Colombier 	}
2129ef1f84bSDavid du Colombier 
2139ef1f84bSDavid du Colombier 	settime(1, -1, nil);
2149ef1f84bSDavid du Colombier 
215*532111f7SDavid du Colombier 	/* make venti available.  give it 20% of free memory. */
2169ef1f84bSDavid du Colombier 	if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
2179ef1f84bSDavid du Colombier 		if((fd = open(f[0], OREAD)) >= 0){
2189ef1f84bSDavid du Colombier 			print("venti...");
2199ef1f84bSDavid du Colombier 			memset(buf, 0, sizeof buf);
2209ef1f84bSDavid du Colombier 			pread(fd, buf, 512, 248*1024);
2219ef1f84bSDavid du Colombier 			close(fd);
2229ef1f84bSDavid du Colombier 			if(memcmp(buf, "venti config\n", 13) != 0){
2239ef1f84bSDavid du Colombier 				print("no venti config found on %s\n", f[0]);
2249ef1f84bSDavid du Colombier 				return -1;
2259ef1f84bSDavid du Colombier 			}
2269ef1f84bSDavid du Colombier 			if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
2279ef1f84bSDavid du Colombier 				print("/boot/venti does not exist\n");
2289ef1f84bSDavid du Colombier 				return -1;
2299ef1f84bSDavid du Colombier 			}
2309ef1f84bSDavid du Colombier 			switch(nf){
2319ef1f84bSDavid du Colombier 			case 1:
2329ef1f84bSDavid du Colombier 				f[1] = "tcp!127.1!17034";
2339ef1f84bSDavid du Colombier 			case 2:
2349ef1f84bSDavid du Colombier 				f[2] = "tcp!127.1!8000";
2359ef1f84bSDavid du Colombier 			}
2369ef1f84bSDavid du Colombier 			configloopback();
237*532111f7SDavid du Colombier 			run("/boot/venti", "-m", "20", "-c", f[0],
238*532111f7SDavid du Colombier 				"-a", f[1], "-h", f[2], nil);
2399ef1f84bSDavid du Colombier 			/*
2409ef1f84bSDavid du Colombier 			 * If the announce address is tcp!*!foo, then set
2419ef1f84bSDavid du Colombier 			 * $venti to tcp!127.1!foo instead, which is actually dialable.
2429ef1f84bSDavid du Colombier 			 */
2439ef1f84bSDavid du Colombier 			if((p = strstr(f[1], "!*!")) != 0){
2449ef1f84bSDavid du Colombier 				*p = 0;
2459ef1f84bSDavid du Colombier 				snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
2469ef1f84bSDavid du Colombier 				f[1] = buf;
2479ef1f84bSDavid du Colombier 			}
2489ef1f84bSDavid du Colombier 			setenv("venti", f[1]);
2499ef1f84bSDavid du Colombier 		}else{
2509ef1f84bSDavid du Colombier 			/* set up the network so we can talk to the venti server */
2519ef1f84bSDavid du Colombier 			/* this is such a crock. */
2529ef1f84bSDavid du Colombier 			configip(nf, f, 0);
2539ef1f84bSDavid du Colombier 			setenv("venti", f[0]);
2549ef1f84bSDavid du Colombier 		}
2559ef1f84bSDavid du Colombier 	}
2569ef1f84bSDavid du Colombier 
257*532111f7SDavid du Colombier 	/* start fossil.  give it 20% of free memory. */
2589ef1f84bSDavid du Colombier 	print("fossil(%s)...", partition);
259*532111f7SDavid du Colombier 	run("/boot/fossil", "-m", "20", "-f", partition,
260*532111f7SDavid du Colombier 		"-c", "srv -A fboot", "-c", "srv -p fscons", nil);
2619ef1f84bSDavid du Colombier 	fd = open("#s/fboot", ORDWR);
2629ef1f84bSDavid du Colombier 	if(fd < 0){
263*532111f7SDavid du Colombier 		warning("open #s/fboot");
2649ef1f84bSDavid du Colombier 		return -1;
2659ef1f84bSDavid du Colombier 	}
266*532111f7SDavid du Colombier 	remove("#s/fboot");  /* we'll repost fd as #s/boot after fversion(fd) */
2679ef1f84bSDavid du Colombier 	return fd;
2689ef1f84bSDavid du Colombier }
2699ef1f84bSDavid du Colombier 
2709ef1f84bSDavid du Colombier int
connectlocal(void)2719ef1f84bSDavid du Colombier connectlocal(void)
2729ef1f84bSDavid du Colombier {
2739ef1f84bSDavid du Colombier 	int fd;
2749ef1f84bSDavid du Colombier 
2759ef1f84bSDavid du Colombier 	if(bind("#c", "/dev", MREPL) < 0)
2769ef1f84bSDavid du Colombier 		fatal("bind #c");
2779ef1f84bSDavid du Colombier 	if(bind("#p", "/proc", MREPL) < 0)
2789ef1f84bSDavid du Colombier 		fatal("bind #p");
2799ef1f84bSDavid du Colombier 	bind("#S", "/dev", MAFTER);
2809ef1f84bSDavid du Colombier 	bind("#k", "/dev", MAFTER);
281*532111f7SDavid du Colombier 	bind("#u", "/dev", MAFTER);
2829ef1f84bSDavid du Colombier 	bind("#æ", "/dev", MAFTER);
283*532111f7SDavid du Colombier 	mountusbparts();	/* make partfs partitions visible again */
2849ef1f84bSDavid du Colombier 
2859ef1f84bSDavid du Colombier 	if((fd = connectlocalfossil()) < 0)
286*532111f7SDavid du Colombier 		fd = connectlocalkfs();
2879ef1f84bSDavid du Colombier 	return fd;
2889ef1f84bSDavid du Colombier }
289