xref: /plan9/sys/src/9/boot/local.c (revision a2ede17577e07b9f98ba4ee93647f95654b05966)
1 #include <u.h>
2 #include <libc.h>
3 #include <../boot/boot.h>
4 
5 static char diskname[64];
6 static char *disk;
7 static char **args;
8 
9 void
configlocal(Method * mp)10 configlocal(Method *mp)
11 {
12 	char *p, *inibootdisk;
13 	int n;
14 
15 	inibootdisk = getenv("bootdisk");
16 	if(*sys == '/' || *sys == '#'){
17 		/*
18 		 *  if the user specifies the disk in the boot cmd or
19 		 * 'root is from' prompt, use it
20 		 */
21 		disk = sys;
22 	} else if(strncmp(argv0, "dksc(0,", 7) == 0){
23 		/*
24 		 *  on many mips arg0 of the boot command specifies the
25 		 *  scsi logical unit number
26 		 */
27 		p = strchr(argv0, ',');
28 		n = strtoul(p+1, 0, 10);
29 		sprint(diskname, "#w%d/sd%dfs", n, n);
30 		disk = diskname;
31 	} else if(mp->arg){
32 		/*
33 		 *  a default is optionally supplied when the kernel is made
34 		 */
35 		disk = mp->arg;
36 	} else if(inibootdisk != nil && *inibootdisk)
37 		/* plan9.ini overrides default from config file */
38 		disk = inibootdisk;
39 	else if(bootdisk != nil && *bootdisk){
40 		/*
41 		 *  an environment variable from a pc's plan9.ini or
42 		 *  from the mips nvram or generated by the kernel
43 		 *  is the last resort.
44 		 */
45 		disk = bootdisk;
46 	}
47 
48 	/* if we've decided on one, pass it on to all programs */
49 	if(disk) {
50 		bootdisk = disk;
51 		setenv("bootdisk", bootdisk);
52 	}
53 }
54 
55 int
connectlocalkfs(void)56 connectlocalkfs(void)
57 {
58 	int i, pid, fd, p[2];
59 	char partition[64];
60 	char *dev;
61 	char **arg, **argp;
62 	Dir *d;
63 
64 	if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
65 		return -1;
66 
67 	dev = disk ? disk : bootdisk;
68 	snprint(partition, sizeof partition, "%sfs", dev);
69 	fd = open(partition, OREAD);
70 	if(fd < 0){
71 		strcpy(partition, dev);
72 		fd = open(partition, OREAD);
73 		if(fd < 0)
74 			return -1;
75 	}
76 	/*
77 	 * can't do this check -- might be some other server posing as kfs.
78 	 *
79 	memset(buf, 0, sizeof buf);
80 	pread(fd, buf, 512, 0);
81 	close(fd);
82 	if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
83 		if(strstr(partition, "/fs"))
84 			print("no kfs file system found on %s\n", partition);
85 		return -1;
86 	}
87 	 *
88 	 */
89 	d = dirfstat(fd);
90 	close(fd);
91 	if(d == nil)
92 		return -1;
93 	if(d->mode&DMDIR){
94 		free(d);
95 		return -1;
96 	}
97 	free(d);
98 
99 	print("kfs...");
100 	if(pipe(p)<0)
101 		fatal("pipe");
102 	switch(pid = fork()){
103 	case -1:
104 		fatal("fork");
105 	case 0:
106 		arg = malloc((bargc+5)*sizeof(char*));
107 		argp = arg;
108 		*argp++ = "kfs";
109 		*argp++ = "-f";
110 		*argp++ = partition;
111 		*argp++ = "-s";
112 		for(i=1; i<bargc; i++)
113 			*argp++ = bargv[i];
114 		*argp = 0;
115 
116 		dup(p[0], 0);
117 		dup(p[1], 1);
118 		close(p[0]);
119 		close(p[1]);
120 		exec("/boot/kfs", arg);
121 		fatal("can't exec kfs");
122 	default:
123 		break;
124 	}
125 	for(;;){
126 		if((i = waitpid()) == -1)
127 			fatal("waitpid for kfs failed");
128 		if(i == pid)
129 			break;
130 	}
131 
132 	close(p[1]);
133 	return p[0];
134 }
135 
136 void
runv(char ** argv)137 runv(char **argv)
138 {
139 	int i, pid;
140 
141 	switch(pid = fork()){
142 	case -1:
143 		fatal("fork");
144 	case 0:
145 		exec(argv[0], argv);
146 		fatal(smprint("can't exec %s: %r", argv[0]));
147 	default:
148 		while ((i = waitpid()) != pid && i != -1)
149 			;
150 		if(i == -1)
151 			fatal(smprint("wait failed running %s", argv[0]));
152 	}
153 }
154 
155 void
run(char * file,...)156 run(char *file, ...)
157 {
158 	runv(&file);
159 }
160 
161 static int
print1(int fd,char * s)162 print1(int fd, char *s)
163 {
164 	return write(fd, s, strlen(s));
165 }
166 
167 void
configloopback(void)168 configloopback(void)
169 {
170 	int fd;
171 
172 	if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
173 		bind("#I", "/net", MAFTER);
174 		if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
175 			fatal("open /net/ipifc/clone for loopback");
176 	}
177 	if(print1(fd, "bind loopback /dev/null") < 0
178 	|| print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
179 		fatal("write /net/ipifc/clone for loopback");
180 }
181 
182 int
connectlocalfossil(void)183 connectlocalfossil(void)
184 {
185 	int fd;
186 	char *venti, *f[32], *p;
187 	int nf;
188 	char partition[128], buf[512];
189 	char *dev;
190 
191 	if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
192 		return -1;
193 
194 	/* look for fossil partition */
195 	dev = disk ? disk : bootdisk;
196 	snprint(partition, sizeof partition, "%sfossil", dev);
197 	fd = open(partition, OREAD);
198 	if(fd < 0){
199 		strcpy(partition, dev);
200 		fd = open(partition, OREAD);
201 		if(fd < 0)
202 			return -1;
203 	}
204 	memset(buf, 0, sizeof buf);
205 	pread(fd, buf, 512, 127*1024);
206 	close(fd);
207 	if(memcmp(buf, "fossil config\n", 14) != 0){
208 		if(strstr(partition, "/fossil"))
209 			print("no fossil config found on %s\n", partition);
210 		return -1;
211 	}
212 
213 	settime(1, -1, nil);
214 
215 	/* make venti available.  give it 20% of free memory. */
216 	if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
217 		if((fd = open(f[0], OREAD)) >= 0){
218 			print("venti...");
219 			memset(buf, 0, sizeof buf);
220 			pread(fd, buf, 512, 248*1024);
221 			close(fd);
222 			if(memcmp(buf, "venti config\n", 13) != 0){
223 				print("no venti config found on %s\n", f[0]);
224 				return -1;
225 			}
226 			if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
227 				print("/boot/venti does not exist\n");
228 				return -1;
229 			}
230 			switch(nf){
231 			case 1:
232 				f[1] = "tcp!127.1!17034";
233 			case 2:
234 				f[2] = "tcp!127.1!8000";
235 			}
236 			configloopback();
237 			run("/boot/venti", "-m", "20", "-c", f[0],
238 				"-a", f[1], "-h", f[2], nil);
239 			/*
240 			 * If the announce address is tcp!*!foo, then set
241 			 * $venti to tcp!127.1!foo instead, which is actually dialable.
242 			 */
243 			if((p = strstr(f[1], "!*!")) != 0){
244 				*p = 0;
245 				snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
246 				f[1] = buf;
247 			}
248 			setenv("venti", f[1]);
249 		}else{
250 			/* set up the network so we can talk to the venti server */
251 			/* this is such a crock. */
252 			configip(nf, f, 0);
253 			setenv("venti", f[0]);
254 		}
255 	}
256 
257 	/* start fossil.  give it 20% of free memory. */
258 	print("fossil(%s)...", partition);
259 	run("/boot/fossil", "-m", "20", "-f", partition,
260 		"-c", "srv -A fboot", "-c", "srv -p fscons", nil);
261 	fd = open("#s/fboot", ORDWR);
262 	if(fd < 0){
263 		warning("open #s/fboot");
264 		return -1;
265 	}
266 	remove("#s/fboot");  /* we'll repost fd as #s/boot after fversion(fd) */
267 	return fd;
268 }
269 
270 int
connectlocal(void)271 connectlocal(void)
272 {
273 	int fd;
274 
275 	if(bind("#c", "/dev", MREPL) < 0)
276 		fatal("bind #c");
277 	if(bind("#p", "/proc", MREPL) < 0)
278 		fatal("bind #p");
279 	bind("#S", "/dev", MAFTER);
280 	bind("#k", "/dev", MAFTER);
281 	bind("#u", "/dev", MAFTER);
282 	bind("#æ", "/dev", MAFTER);
283 	mountusbparts();	/* make partfs partitions visible again */
284 
285 	if((fd = connectlocalfossil()) < 0)
286 		fd = connectlocalkfs();
287 	return fd;
288 }
289