#include #include #include #define DEFFILE "/mips/9" #define DEFSYS "bit!bootes" Fcall hdr; char *scmd; char bootfile[5*NAMELEN]; char conffile[5*NAMELEN]; char sys[NAMELEN]; char buf[4*1024]; int fd; int cfd; int efd; typedef struct address { char *name; char *cmd; } Address; Address addr[] = { { "ross", "connect 020701005eff" }, { "bootes", "connect 0800690203f3" }, { "helix", "connect 080069020427" }, { "spindle", "connect 0800690202df" }, { "r70", "connect 08002b04265d" }, { 0 } }; struct a_out_h { ulong magic; /* magic and sections */ ulong timestamp; /* time and date */ ulong size; /* (HEADR+textsize+datsize) */ ulong symsize; /* nsyms */ ulong opt; /* size of optional hdr and flags */ ulong magicversion; /* magic and version */ ulong text; /* sizes */ ulong data; ulong bss; ulong entryva; /* va of entry */ ulong textva; /* va of base of text */ ulong dataca; /* va of base of data */ ulong bssva; /* va of base of bss */ ulong gpregmask; /* gp reg mask */ ulong dummy1; ulong dummy1; ulong dummy1; ulong dummy1; ulong gpvalue; /* gp value ?? */ ulong mystery; /* complete mystery */ } a_out; /* * predeclared */ int dkdial(char *); int nonetdial(char *); int bitdial(char *); int readseg(int, int, long, long, int); int readkernel(int); int readconf(int); int outin(char *, char *, int); void prerror(char *); void error(char *); void boot(int, char *); /* * usage: 9b [-a] [server] [file] * * default server is `bitbootes', default file is `/sys/src/9/mips/9' */ main(int argc, char *argv[]) { int i; char *sysname; open("#c/cons", 0); open("#c/cons", 1); open("#c/cons", 1); sysname = argv[0]; argv++; argc--; while(argc > 0){ if(argv[0][0] == '-'){ 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; } boot(0, sysname); for(;;){ if(fd > 0) close(fd); if(cfd > 0) close(cfd); fd = cfd = 0; boot(1, sysname); } } int bitdial(char *arg) { return open("#3/bit3", ORDWR); } int nonetdial(char *arg) { int efd, cfd, fd; Address *a; static int mounted; for(a = addr; a->name; a++){ if(strcmp(a->name, arg) == 0) break; } if(a->name == 0){ print("can't convert nonet address to ether address\n"); return -1; } if(!mounted){ /* * 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 -1; } if(write(efd, "connect 0x900", sizeof("connect 0x900")-1)<0){ close(efd); prerror("connect 0x900"); return -1; } if(write(efd, "push noether", sizeof("push noether")-1)<0){ close(efd); prerror("push noether"); return -1; } if(write(efd, "config nonet", sizeof("config nonet")-1)<0){ close(efd); prerror("config nonet"); return -1; } mounted = 1; } /* * grab a nonet channel and call up the file server */ fd = open("#nnonet/2/data", 2); if(fd < 0) { prerror("opening #nnonet/2/data"); return -1; } cfd = open("#nnonet/2/ctl", 2); if(cfd < 0){ close(fd); fd = -1; prerror("opening #nnonet/2/ctl"); return -1; } if(write(cfd, a->cmd, strlen(a->cmd))<0){ close(cfd); close(fd); cfd = fd = -1; prerror(a->cmd); return -1; } return fd; } 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", 2); 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("#kdk/5/data", 2); if(fd < 0) { prerror("opening #kdk/5/data"); return -1; } cfd = open("#kdk/5/ctl", 2); if(cfd < 0){ close(fd); fd = -1; prerror("opening #kdk/5/ctl"); return -1; } sprint(cmd, "connect %s", arg); if(write(cfd, cmd, strlen(cmd))<0){ close(cfd); close(fd); cfd = fd = -1; prerror(cmd); return -1; } return fd; } void boot(int ask, char *addr) { int n, tries; char *srvname; if(ask){ outin("bootfile", bootfile, sizeof(bootfile)); outin("server", sys, sizeof(sys)); } for(tries = 0; tries < 5; tries++){ fd = -1; if(strncmp(sys, "bit!", 4) == 0) fd = bitdial(srvname = &sys[4]); else if(strncmp(sys, "dk!", 3) == 0) fd = dkdial(srvname = &sys[3]); else if(strncmp(sys, "nonet!", 6) == 0) fd = nonetdial(srvname = &sys[6]); else fd = nonetdial(srvname = sys); if(fd >= 0) break; print("can't connect, retrying...\n"); sleep(1000); } if(fd < 0){ print("can't connect\n"); return; } 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; } reread: n = read(fd, buf, sizeof buf); if(n <= 0){ prerror("read nop"); return; } 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; } 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("mount..."); if(bind("/", "/", MREPL) < 0){ prerror("bind"); return; } if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0){ prerror("mount"); return; } close(fd); sprint(conffile, "/mips/conf/%s", addr); print("%s...", conffile); while((fd = open(conffile, OREAD)) < 0){ outin("conffile", conffile, sizeof(conffile)); } if(readconf(fd) < 0) prerror("readconf"); close(fd); print("%s...", bootfile); while((fd = open(bootfile, OREAD)) < 0){ outin("bootfile", bootfile, sizeof(bootfile)); } readkernel(fd); prerror("couldn't read kernel"); } /* * 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; } /* * read a segment into memory */ int readseg(int in, int out, long inoff, long outoff, int len) { long n, i; if(seek(in, inoff, 0) < 0){ prerror("seeking bootfile"); return -1; } if(seek(out, outoff, 0) != outoff){ prerror("seeking #b/mem"); return -1; } for(; len > 0; len -= n){ if((n = read(in, buf, sizeof buf)) <= 0){ prerror("reading bootfile"); return -1; } if(write(out, buf, n) != n){ prerror("writing #b/mem"); return -1; } } return 0; } /* * set a configuration value */ /* * read the configuration */ int readconf(int fd) { int bfd; int n; long x; /* * read the config file */ n = read(fd, buf, sizeof(buf)-1); if(n <= 0) return -1; buf[n] = 0; /* * write into 4 meg - 4k */ bfd = open("#b/mem", OWRITE); if(bfd < 0){ prerror("can't open #b/mem"); return; } x = 0x80000000 | 4*1024*1024 - 4*1024; if(seek(bfd, x, 0) != x){ close(bfd); return -1; } if(write(bfd, buf, n+1) != n+1){ close(bfd); return -1; } close(bfd); return 0; } /* * read the kernel into memory and jump to it */ int readkernel(int fd) { int n; int bfd; bfd = open("#b/mem", OWRITE); if(bfd < 0){ prerror("can't open #b/mem"); return; } n = read(fd, &a_out, sizeof(a_out)); if(n <= 0){ prerror("can't read boot file"); close(bfd); return; } print("\n%d", a_out.text); if(readseg(fd, bfd, 20*4, a_out.textva, a_out.text)<0){ prerror("can't read boot file"); close(bfd); return; } print("+%d", a_out.data); if(readseg(fd, bfd, 20*4 + a_out.text, a_out.textva + a_out.text, a_out.data)<0){ prerror("can't read boot file"); close(bfd); return; } print("+%d", a_out.bss); close(bfd); bfd = open("#b/boot", OWRITE); if(bfd < 0){ prerror("can't open #b/boot"); return; } print(" entry: 0x%ux\n", a_out.entryva); sleep(1000); if(write(bfd, &a_out.entryva, sizeof a_out.entryva) != sizeof a_out.entryva){ prerror("can't start kernel"); close(bfd); } return; } /* * prompt and get input */ int outin(char *prompt, char *def, 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){ buf[n-1] = 0; strcpy(def, buf); } return n; }