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