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