#include #include #include #define DEFSYS "bitbootes" #define DEFFILE "/mips/9" Fcall hdr; char *sys; char *scmd; char *bootfile; char sbuf[2*NAMELEN]; char buf[4*1024]; int fd; int cfd; int efd; typedef struct address { char *name; char *cmd; char *srvname; } Address; Address addr[] = { { "bitbootes", "bitconnect", "bit!bootes" }, { "ross", "connect 020701005eff", "nonet!ross" }, { "bootes", "connect 080069020205", "nonet!bootes" }, { "helix", "connect 080069020427", "nonet!helix" }, { "spindle", "connect 0800690202df", "nonet!spindle" }, { "r70", "connect 08002b04265d", "nonet!r70" }, { 0 } }; /* * predeclared */ Address* lookup(char *); int outin(char *, char *, char *, int); void prerror(char *); void error(char *); void boot(int); /* * usage: 9b [-a] [server] [file] * * default server is `bitbootes', default file is `/mips/9' */ main(int argc, char *argv[]) { int i; int manual=0; open("#c/cons", 0); open("#c/cons", 1); open("#c/cons", 1); i = create("#e/sysname", 1, 0666); if(i < 0) error("sysname"); if(write(i, argv[0], strlen(argv[0])) <= 0) error("sysname"); close(i); argv++; argc--; while(argc > 0){ if(argv[0][0] == '-'){ if(argv[0][1] == 'm') manual = 1; argc--; argv++; } else break; } sys = DEFSYS; bootfile = DEFFILE; switch(argc){ case 1: bootfile = argv[0]; break; case 2: bootfile = argv[0]; sys = argv[1]; break; } boot(manual); for(;;){ if(fd > 0) close(fd); if(cfd > 0) close(cfd); if(efd > 0) close(efd); fd = cfd = efd = 0; boot(1); } } void boot(int ask) { int n, f; Address *a; if(ask){ outin("server", sys, sbuf, sizeof(sbuf)); sys = sbuf; } a = lookup(sys); if(a == 0){ fprint(2, "boot: %s unknown\n", sys); return; } scmd = a->cmd; /* * for the bit, we skip all the ether goo */ if(strcmp(scmd, "bitconnect") == 0){ fd = open("#3/bit3", ORDWR); if(fd < 0){ prerror("opening #3/bit3"); return; } goto Mesg; } /* * grab a lance channel, make it recognize ether type 0x900, * and push the nonet ethernet multiplexor onto it. */ efd = open("#l/1/ctl", 2); if(efd < 0){ prerror("opening #l/1/ctl"); return; } if(write(efd, "connect 0x900", sizeof("connect 0x900")-1)<0){ prerror("connect 0x900"); return; } if(write(efd, "push noether", sizeof("push noether")-1)<0){ prerror("push noether"); return; } if(write(efd, "config nonet", sizeof("config nonet")-1)<0){ prerror("config nonet"); return; } /* * grab a nonet channel and call up the ross file server */ fd = open("#nnonet/2/data", 2); if(fd < 0) { prerror("opening #nnonet/2/data"); return; } cfd = open("#nnonet/2/ctl", 2); if(cfd < 0){ prerror("opening #nnonet/2/ctl"); return; } if(write(cfd, scmd, strlen(scmd))<0){ prerror(scmd); return; } Mesg: print("nop..."); hdr.type = Tnop; hdr.tag = ~0; n = convS2M(&hdr, buf); if(write(fd, buf, n) != n){ print("n = %d\n", n); prerror("write nop"); return; } n = read(fd, buf, sizeof buf); if(n <= 0){ prerror("read nop"); return; } 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; } if(hdr.type != Rnop){ prerror("not Rnop"); return; } if(hdr.tag != ~0){ prerror("tag not ~0"); return; } print("session..."); hdr.type = Tsession; hdr.tag = ~0; n = convS2M(&hdr, buf); if(write(fd, buf, n) != n){ prerror("write session"); return; } n = read(fd, buf, sizeof buf); if(n <= 0){ prerror("read session"); return; } if(convM2S(buf, &hdr, n) == 0){ prerror("format session"); return; } if(hdr.tag != ~0){ prerror("tag not ~0"); return; } if(hdr.type == Rerror){ fprint(2, "boot: error %s\n", hdr.ename); return; } if(hdr.type != Rsession){ prerror("not Rsession"); return; } print("post..."); sprint(buf, "#s/%s", a->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); f = create("#s/boot", 1, 0666); if(f < 0) error("create"); sprint(buf, "%d", fd); if(write(f, buf, strlen(buf)) != strlen(buf)) error("write"); close(f); print("mount..."); if(bind("/", "/", MREPL) < 0) error("bind"); if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0) error("mount"); print("success\n"); close(fd); if(ask) execl("/mips/init", "init", "-m", 0); else execl("/mips/init", "init", 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); } /* * lookup the address for a system */ Address * lookup(char *arg) { Address *a; if(strcmp(arg, "?")==0 || strcmp(arg, "help")==0){ for(a = addr; a->name; a++) print("%s\n", a->name); return 0; } for(a = addr; a->name; a++){ if(strcmp(a->name, arg) == 0) return a; } return 0; } /* * prompt and get input */ int outin(char *prompt, char *def, char *buf, int len) { int n; 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) strcpy(buf, def); else buf[n-1] = 0; return n; }