#include #include #include #define DEFSYS "cyc!bootes" #define DEFFILE "/mips/9" Fcall hdr; char *scmd; char buf[4*1024]; char bootfile[5*NAMELEN]; char sys[NAMELEN]; int printcol; /* so we can use the kernel's small print */ int fd; int cfd; int efd; int setkey; /* * predeclared */ int outin(char *, char *, int); void prerror(char *); void error(char *); void boot(int); int dkdial(char *); int bitdial(char *); int preamble(int); void srvcreate(char*, int); void settime(void); void key(void); int passwd(char*, int); int passtokey(char*, char*, int); /* * usage: 9b [-mp] [server] [file] * * default server is `bitbootes', default file is `/mips/9' */ void main(int argc, char *argv[]) { int i; int manual=0; open("#c/cons", OREAD); open("#c/cons", OWRITE); open("#c/cons", OWRITE); argv++; argc--; while(argc > 0){ if(argv[0][0] == '-'){ if(argv[0][1] == 'm') manual = 1; else if(argv[0][1] == 'k') setkey = 1; argc--; argv++; } else break; } strcpy(sys, DEFSYS); strcpy(bootfile, DEFFILE); switch(argc){ case 1: strcpy(bootfile, argv[0]); break; case 2: strcpy(bootfile, argv[0]); strcpy(sys, argv[1]); break; } key(); boot(manual); for(;;){ if(fd > 0) close(fd); if(cfd > 0) close(cfd); fd = cfd = 0; boot(1); } } int bitdial(char *arg) { USED(arg); return open("#3/bit3", ORDWR); } int dkdial(char *arg) { int fd; char cmd[64]; static int mounted; if(!mounted){ /* * grab the hsvme and configure it for a datakit */ efd = open("#h/ctl", ORDWR); if(efd < 0){ prerror("opening #h/ctl"); return -1; } if(write(efd, "push dkmux", sizeof("push dkmux")-1)<0){ close(efd); prerror("push dkmux"); return -1; } if(write(efd, "config 4 256 restart dk", sizeof("config 4 256 restart dk")-1)<0){ close(efd); prerror("config 4 256 restart dk"); return -1; } mounted = 1; sleep(2000); /* wait for things to settle down */ } /* * grab a datakit channel and call up the file server */ fd = open("#k/dk/5/data", ORDWR); if(fd < 0) { prerror("opening #k/dk/5/data"); return -1; } cfd = open("#k/dk/5/ctl", ORDWR); if(cfd < 0){ close(fd); prerror("opening #k/dk/5/ctl"); return -1; } sprint(cmd, "connect %s", arg); if(write(cfd, cmd, strlen(cmd))<0){ close(cfd); close(fd); prerror(cmd); return -1; } return fd; } int hotdial(char *arg) { USED(arg); return open("#H/hotrod", ORDWR); } int preamble(int fd) { int n; print("nop..."); hdr.type = Tnop; hdr.tag = NOTAG; n = convS2M(&hdr, buf); if(write(fd, buf, n) != n){ print("n = %d\n", n); prerror("write nop"); return 0; } reread: n = read(fd, buf, sizeof buf); if(n <= 0){ prerror("read nop"); return 0; } if(n == 2) goto reread; if(convM2S(buf, &hdr, n) == 0) { print("n = %d; buf = %.2x %.2x %.2x %.2x\n", n, buf[0], buf[1], buf[2], buf[3]); prerror("format nop"); return 0; } if(hdr.type != Rnop){ prerror("not Rnop"); return 0; } if(hdr.tag != NOTAG){ prerror("tag not NOTAG"); return 0; } print("session..."); hdr.type = Tsession; hdr.tag = NOTAG; n = convS2M(&hdr, buf); if(write(fd, buf, n) != n){ prerror("write session"); return 0; } n = read(fd, buf, sizeof buf); if(n <= 0){ prerror("read session"); return 0; } if(convM2S(buf, &hdr, n) == 0){ prerror("format session"); return 0; } if(hdr.tag != NOTAG){ prerror("tag not NOTAG"); return 0; } if(hdr.type == Rerror){ fprint(2, "boot: error %s\n", hdr.ename); return 0; } if(hdr.type != Rsession){ prerror("not Rsession"); return 0; } return 1; } void boot(int ask) { int n, f, tries; if(ask) outin("server", sys, sizeof(sys)); for(tries = 0; tries < 5; tries++){ fd = -1; if(strncmp(sys, "bit!", 4) == 0) fd = bitdial(&sys[4]); else if(strncmp(sys, "cyc!", 4) == 0) fd = hotdial(&sys[4]); else if(strncmp(sys, "dk!", 3) == 0) fd = dkdial(&sys[3]); if(fd >= 0) break; print("can't connect, retrying...\n"); sleep(1000); } if(fd < 0){ print("can't connect\n"); return; } if(!preamble(fd)) return; srvcreate("boot", fd); srvcreate("bootes", fd); print("mount..."); if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0) error("mount"); settime(); print("success\n"); if(ask){ execl("/mips/init", "init", "-mc", 0); } else { execl("/mips/init", "init", "-c", 0); } error("/mips/init"); } /* * print error */ void prerror(char *s) { char buf[64]; errstr(buf); fprint(2, "boot: %s: %s\n", s, buf); } /* * print error and exit */ void error(char *s) { char buf[64]; errstr(buf); fprint(2, "boot: %s: %s\n", s, buf); exits(0); } /* * prompt and get input */ int outin(char *prompt, char *def, int len) { int n; char buf[256]; do{ print("%s[%s]: ", prompt, def); n = read(0, buf, len); }while(n==0); if(n < 0) error("can't read #c/cons; please reboot"); if(n != 1){ buf[n-1] = 0; strcpy(def, buf); } return n; } void srvcreate(char *name, int fd) { char *srvname; int f; srvname = strrchr(name, '/'); if(srvname) srvname++; else srvname = name; sprint(buf, "#s/%s", srvname); f = create(buf, 1, 0666); if(f < 0) error("create"); sprint(buf, "%d", fd); if(write(f, buf, strlen(buf)) != strlen(buf)) error("write"); close(f); } void settime(void) { char dirbuf[DIRLEN]; Dir dir; int f; print("time..."); /* * set the time from the access time of the root * of the file server */ f = open("#s/boot", ORDWR); if(f < 0) return; if(mount(f, "/n/boot", MREPL, "", "") < 0){ close(f); return; } close(f); if(stat("/n/boot", dirbuf) < 0) error("stat"); convM2D(dirbuf, &dir); sprint(dirbuf, "%ld", dir.atime); unmount(0, "/n/boot"); f = open("#c/time", OWRITE); write(f, dirbuf, strlen(dirbuf)); close(f); } void key(void) { char password[20], key[7]; int prompt, fd; prompt = setkey; fd = open("#r/nvram", ORDWR); if(fd < 0){ prompt = 1; prerror("can't open nvram"); } if(prompt){ do if(passwd(password, sizeof password) < 0){ prerror("can't read cons"); return; } while(!passtokey(key, password, strlen(password))); }else if(seek(fd, 1024+900, 0) < 0 || read(fd, key, 7) != 7){ close(fd); prerror("can't read key from nvram"); } if(setkey && seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7){ close(fd); prerror("can't write key to nvram"); } close(fd); fd = open("#c/key", OWRITE); if(fd < 0) prerror("can't open key"); else if(write(fd, key, 7) != 7) prerror("can't write key"); close(fd); } int passwd(char *p, int len) { char c; int i, n, fd; fd = open("#c/consctl", OWRITE); if(fd < 0) return -1; write(fd, "rawon", 5); Prompt: print("password: "); n = 0; for(;;){ do{ i = read(0, &c, 1); if(i < 0){ close(fd); return -1; } }while(i == 0); switch(c){ case '\n': p[n] = '\0'; close(fd); print("\n"); return 0; case '\b': if(n > 0) n--; break; case 'u' - 'a' + 1: /* cntrl-u */ print("\n"); goto Prompt; default: if(n < len - 1) p[n++] = c; break; } } } int passtokey(char *key, char *p, int n) { uchar t[10]; int c; memset(t, ' ', sizeof t); if(n < 5) return 0; if(n > 10) n = 10; strncpy((char*)t, p, n); if(n >= 9){ c = p[8] & 0xf; if(n == 10) c += p[9] << 4; for(n = 0; n < 8; n++) if(c & (1 << n)) t[n] -= ' '; } for(n = 0; n < 7; n++) key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1))); return 1; }