From a58e250508740bf66041bd946455d286b4603dec Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 17 Mar 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-03-17 --- boot/aux.c | 144 ++++++++++++++++++++ boot/boot.c | 327 ++++++++++++++++++++++++++++++++++++++++++++++ boot/boot.h | 59 +++++++++ boot/getpasswd.c | 43 ++++++ boot/key.c | 42 ++++++ boot/local.c | 57 ++++++++ boot/userpasswd.c | 92 +++++++++++++ port/devcons.c | 2 +- port/devmnt.c | 7 +- port/page.c | 3 +- power/devhotrod.c | 4 +- 11 files changed, 771 insertions(+), 9 deletions(-) create mode 100644 boot/aux.c create mode 100644 boot/boot.c create mode 100644 boot/boot.h create mode 100644 boot/getpasswd.c create mode 100644 boot/key.c create mode 100644 boot/local.c create mode 100644 boot/userpasswd.c diff --git a/boot/aux.c b/boot/aux.c new file mode 100644 index 0000000000000000000000000000000000000000..72aa782bac7649e312938c71d3980196abfe292d --- /dev/null +++ b/boot/aux.c @@ -0,0 +1,144 @@ +#include +#include +#include <../boot/boot.h> + +int +plumb(char *dir, char *dest, int *efd, char *here) +{ + char buf[128]; + char name[128]; + int n; + + sprint(name, "%s/clone", dir); + efd[0] = open(name, ORDWR); + if(efd[0] < 0) + return -1; + n = read(efd[0], buf, sizeof(buf)-1); + if(n < 0){ + close(efd[0]); + return -1; + } + buf[n] = 0; + sprint(name, "%s/%s/data", dir, buf); + if(here){ + sprint(buf, "announce %s", here); + if(sendmsg(efd[0], buf) < 0){ + close(efd[0]); + return -1; + } + } + sprint(buf, "connect %s", dest); + if(sendmsg(efd[0], buf) < 0){ + close(efd[0]); + return -1; + } + efd[1] = open(name, ORDWR); + if(efd[1] < 0){ + close(efd[0]); + return -1; + } + return efd[1]; +} + +int +sendmsg(int fd, char *msg) +{ + int n; + + n = strlen(msg); + if(write(fd, msg, n) != n) + return -1; + return 0; +} + +void +warning(char *s) +{ + char buf[ERRLEN]; + + errstr(buf); + fprint(2, "boot: %s: %s\n", s, buf); +} + +void +fatal(char *s) +{ + char buf[ERRLEN]; + + errstr(buf); + fprint(2, "boot: %s: %s\n", s, buf); + exits(0); +} + +int +readenv(char *name, char *buf, int len) +{ + int f, n; + char ename[2*NAMELEN]; + + sprint(ename, "#e/%s", name); + buf[0] = 0; + f = open(ename, OREAD); + if(f < 0) + return -1; + n = read(f, buf, len-1); + if(n >= 0) + buf[n] = 0; + close(f); + return 0; +} + +void +setenv(char *name, char *val) +{ + int f; + char ename[2*NAMELEN]; + + sprint(ename, "#e/%s", name); + f = create(ename, 1, 0666); + if(f < 0) + return; + write(f, val, strlen(val)); + close(f); +} + +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) + fatal(buf); + sprint(buf, "%d", fd); + if(write(f, buf, strlen(buf)) != strlen(buf)) + fatal("write"); + close(f); +} + +int +outin(char *prompt, char *def, int len) +{ + int n; + char buf[256]; + + do{ + print("%s[%s]: ", prompt, *def ? def : "no default"); + n = read(0, buf, len); + }while(n==0); + if(n < 0) + fatal("can't read #c/cons; please reboot"); + if(n != 1){ + buf[n-1] = 0; + strcpy(def, buf); + } + return n; +} diff --git a/boot/boot.c b/boot/boot.c new file mode 100644 index 0000000000000000000000000000000000000000..7f62079a78940effbe96512ebeed16dbbcf8a8c7 --- /dev/null +++ b/boot/boot.c @@ -0,0 +1,327 @@ +#include +#include +#include +#include "../port/bootp.h" +#include "../port/arp.h" + +#define DEFSYS "bootes" +typedef struct Net Net; +typedef struct Flavor Flavor; + +enum +{ + Nterm = 4, + CtrlD = 4, + Cr = 13, + View = 0x80, +}; + +Fcall hdr; +int printcol; + +char cputype[NAMELEN]; +char terminal[NAMELEN]; +char sys[2*NAMELEN]; +char username[NAMELEN]; + +int mflag; +int fflag; +int kflag; + +void nop(int); +void session(int); +int cache(int); +void swapproc(void); +void settime(int); +Method *rootserver(char*); + +void +main(int argc, char *argv) +{ + int fd; + Method *mp; + char cmd[64]; + char flags[5]; + int islocal; + + sleep(1000); + + open("#c/cons", OREAD); + open("#c/cons", OWRITE); + open("#c/cons", OWRITE); + + ARGBEGIN{ + case 'u': + strcpy(username, ARGF()); + break; + case 'k': + kflag = 1; + break; + case 'm': + mflag = 1; + break; + case 'f': + fflag = 1; + break; + }ARGEND + + readenv("cputype", cputype, sizeof(cputype)); + readenv("terminal", terminal, sizeof(cputype)); + + /* + * pick a method and initialize it + */ + mp = rootserver(*argv); + islocal = strcmp(mp->name, "local") == 0; + (*mp->config)(mp); + + /* + * get/set key or password + */ + (*pword)(mp); + + /* + * connect to the root file system + */ + fd = (*mp->connect)(); + if(fd < 0) + fatal("can't connect to file server"); + if(!islocal){ + nop(fd); + session(fd); + fd = cache(fd); + srvcreate(sys, fd); + } + srvcreate("boot", fd); + + /* + * create the name space, mount the root fs + */ + if(bind("/", "/", MREPL) < 0) + fatal("bind"); + if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0) + fatal("mount"); + close(fd); + + /* + * start local fs if its not the root file server + */ + if(!islocal){ + for(mp = method; mp->name; mp++) + if(strcmp(mp->name, "local")==0){ + local = (*mp->connect)(mp); + if(local < 0) + break; + if(mount(local, "/n/kfs", MAFTER|MCREATE, "", "") < 0) + fatal("mount"); + close(local); + break; + } + } + + settime(islocal); + swapproc(); + + sleep(1000); + sprint(cmd, "/%s/init", cputype); + sprint(flags, "-%s%s", cpuflag ? "c" : "t", mflag ? "m", ""); + execl(cmd, "init", flags, 0); + fatal(cmd); +} + +/* + * ask user from whence comes the root file system + */ +Method* +rootserver(char *arg) +{ + char prompt[256]; + char reply[64]; + Method *mp; + char *cp; + int n; + + mp = method; + n = 0; + sprint(prompt, "root is from (", mp->name); + for(mp++; mp->name; mp++) + n += sprint(prompt+n, ", %s", mp->name); + sprint(prompt+n, ")"); + + for(;;){ + strcpy(reply, method->name); + if(arg == 0) + outin(prompt, reply, sizeof(reply)); + else + strcpy(reply, arg); + arg = 0; + for(mp = method; mp->name; mp++) + if(*reply == *mp->name){ + cp = strchr(reply, '!'); + if(cp) + strcpy(sys, cp+1); + return mp; + } + if(mp->name == 0) + continue; + } +} + +void +nop(int fd) +{ + long n; + + print("nop..."); + hdr.type = Tnop; + hdr.tag = NOTAG; + n = convS2M(&hdr, buf); + if(write(fd, buf, n) != n) + fatal("write nop"); + n = read(fd, buf, sizeof buf); + if(n==2 && buf[0]=='O' && buf[1]=='K') + n = read(fd, buf, sizeof buf); + if(n <= 0) + fatal("read nop"); + if(convM2S(buf, &hdr, n) == 0) { + print("n = %d; buf = %#.2x %#.2x %#.2x %#.2x\n", + n, buf[0], buf[1], buf[2], buf[3]); + fatal("format nop"); + } + if(hdr.type != Rnop) + fatal("not Rnop"); +} + +void +session(int fd) +{ + long n; + + print("session..."); + hdr.type = Tsession; + hdr.tag = NOTAG; + n = convS2M(&hdr, buf); + if(write(fd, buf, n) != n) + fatal("write session"); + n = read(fd, buf, sizeof buf); + if(n <= 0) + fatal("read session"); + if(convM2S(buf, &hdr, n) == 0) + fatal("format session"); + if(hdr.type == Rerror){ + print("error %s;", hdr.ename); + fatal(hdr.ename); + } + if(hdr.type != Rsession) + fatal("not Rsession"); +} + +int +cache(int fd) +{ + ulong i; + int p[2]; + char d[DIRLEN]; + char partition[2*NAMELEN]; + + if(stat("/cfs", d) < 0) + return fd; + sprint(partition, "%scache", bootdisk); + if(stat(partition, d) < 0) + return fd; + print("cfs..."); + if(pipe(p)<0) + fatal("pipe"); + switch(fork()){ + case -1: + fatal("fork"); + case 0: + close(p[1]); + dup(fd, 0); + close(fd); + dup(p[0], 1); + close(p[0]); + if(format) + execl("/cfs", "bootcfs", "-fs", "-p", partition, 0); + else + execl("/cfs", "bootcfs", "-s", "-p", partition, 0); + break; + default: + close(p[0]); + close(fd); + fd = p[1]; + break; + } + return fd; +} + +void +swapproc(void) +{ + int fd; + + fd = open("#c/swap", OWRITE); + if(fd < 0){ + warning("opening #c/swap"); + return; + } + if(write(fd, "start", 5) <= 0) + warning("starting swap kproc"); +} + +void +settime(int islocal) +{ + int n, f; + int timeset; + Dir dir; + char dirbuf[DIRLEN]; + char *srvname; + + print("time..."); + timeset = 0; + if(islocal){ + /* + * set the time from the real time clock + */ + f = open("#r/rtc", ORDWR); + if(f >= 0){ + if((n = read(f, dirbuf, sizeof(dirbuf)-1)) > 0){ + dirbuf[n] = 0; + timeset = 1; + } + close(f); + } + } + if(timeset == 0){ + /* + * set the time from the access time of the root + */ + 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) + fatal("stat"); + convM2D(dirbuf, &dir); + sprint(dirbuf, "%ld", dir.atime); + unmount(0, "/n/boot"); + /* + * set real time clock if there is one + */ + f = open("#r/rtc", ORDWR); + if(f > 0){ + write(f, dirbuf, strlen(dirbuf)); + close(f); + } + close(f); + } + + f = open("#c/time", OWRITE); + write(f, dirbuf, strlen(dirbuf)); + close(f); +} diff --git a/boot/boot.h b/boot/boot.h new file mode 100644 index 0000000000000000000000000000000000000000..a55681bc639295a5bb5a6673a55266dceecd88f8 --- /dev/null +++ b/boot/boot.h @@ -0,0 +1,59 @@ +typedef struct Method Method; +struct Method +{ + char *name; + void (*config)(Method*); + void (*auth)(Method*); + void (*connect)(Method*); + char *arg; +}; + +extern char terminal[NAMELEN]; +extern char sys[2*NAMELEN]; +extern char password[NAMELEN]; +extern char username[NAMELEN]; +extern char cputype[NAMELEN]; +extern char *bootdisk; +extern char *initflag; +extern void (*pword)(Method*); +extern int kflag; + +/* libc equivalent */ +extern int plumb(char*, char*, int*, char*); +extern int outin(char*, char*, int); +extern int sendmsg(int, char*); +extern void warning(char*); +extern void fatal(char*); +extern int readenv(char*, char*, int); +extern void setenv(char*, char*); +extern void srvcreate(char*, int); +extern int dkauth(void); +extern int dkconnect(void); +extern void userpasswd(int); +extern void getpasswd(char*, int); + +/* methods */ +extern void config9600(Method*); +extern int auth9600(Method*); +extern int connect9600(Method*); +extern void config192000(Method*); +extern int auth192000(Method*); +extern int connect192000(Method*); +extern void confighs(Method*); +extern int authhs(Method*); +extern int connecths(Method*); +extern void configincon(Method*); +extern int authincon(Method*); +extern int connectincon(Method*); +extern void configil(Method*); +extern int authil(Method*); +extern int connectil(Method*); +extern void configtcp(Method*); +extern int authtcp(Method*); +extern int connecttcp(Method*); +extern void configcyc(Method*); +extern int authcyc(Method*); +extern int connectcyc(Method*); +extern void configlocal(Method*); +extern int authlocal(Method*); +extern int connectlocal(Method*); diff --git a/boot/getpasswd.c b/boot/getpasswd.c new file mode 100644 index 0000000000000000000000000000000000000000..b766e254389e869274319e2ba065cddc8f5783e1 --- /dev/null +++ b/boot/getpasswd.c @@ -0,0 +1,43 @@ +#include +#include +#include <../boot/boot.h> + +void +getpasswd(char *p, int len) +{ + char c; + int i, n, fd; + + fd = open("#c/consctl", OWRITE); + if(fd < 0) + fatal("can't open consctl; please reboot"); + write(fd, "rawon", 5); + Prompt: + print("password: "); + n = 0; + for(;;){ + do{ + i = read(0, &c, 1); + if(i < 0) + fatal("can't read cons; please reboot"); + }while(i == 0); + switch(c){ + case '\n': + p[n] = '\0'; + close(fd); + print("\n"); + return; + 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; + } + } +} diff --git a/boot/key.c b/boot/key.c new file mode 100644 index 0000000000000000000000000000000000000000..3822853c780f9aa1e08088d1b7b3f02577c0dbb9 --- /dev/null +++ b/boot/key.c @@ -0,0 +1,42 @@ +#include +#include +#include <../boot/boot.h> + +void +key(Method *mp) +{ + char password[20], key[7]; + int prompt, fd; + + USED(mp); + + prompt = kflag; + fd = open("#r/nvram", ORDWR); + if(fd < 0){ + prompt = 1; + warning("can't open nvram"); + } + if(prompt){ + do + if(getpasswd(password, sizeof password) < 0){ + warning("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); + warning("can't read key from nvram"); + } + if(kflag && seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7){ + close(fd); + warning("can't write key to nvram"); + } + close(fd); + fd = open("#c/key", OWRITE); + if(fd < 0) + warning("can't open key"); + else if(write(fd, key, 7) != 7) + warning("can't write key"); + close(fd); +} + diff --git a/boot/local.c b/boot/local.c new file mode 100644 index 0000000000000000000000000000000000000000..ffdb08955f893356d8b153485420ece2efdce8d6 --- /dev/null +++ b/boot/local.c @@ -0,0 +1,57 @@ +#include +#include +#include <../boot/boot.h> + +static char *disk; + +void +configlocal(Method *mp) +{ + disk = mp->arg; + USED(mp); +} + +int +authlocal(void) +{ + return -1; +} + +int +connectlocal(void) +{ + ulong i; + int p[2]; + char d[DIRLEN]; + char sbuf[32]; + char rbuf[32]; + char *mtpt; + char partition[2*NAMELEN]; + + if(stat("/kfs", d) < 0) + return -1; + sprint(partition, "%sfs", mp->arg ? mp->arg : bootdisk); + if(stat(partition, d) < 0) + return -1; + + if(bind("#c", "/dev", MREPL) < 0) + fatal("bind #c"); + if(bind("#p", "/proc", MREPL) < 0) + fatal("bind #p"); + if(pipe(p)<0) + fatal("pipe"); + switch(fork()){ + case -1: + fatal("fork"); + case 0: + sprint(sbuf, "%d", p[0]); + sprint(rbuf, "%d", p[1]); + execl("/kfs", "kfs", "-f", partition, "-s", sbuf, rbuf, 0); + fatal("can't exec kfs"); + default: + break; + } + + close(p[1]); + return p[0]; +} diff --git a/boot/userpasswd.c b/boot/userpasswd.c new file mode 100644 index 0000000000000000000000000000000000000000..ba331d919c70b13d404e0e035814f52a09619ff5 --- /dev/null +++ b/boot/userpasswd.c @@ -0,0 +1,92 @@ +#include +#include +#include <../boot/boot.h> + +char password[NAMELEN]; + +static 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; +} + +/* + * get/set user name and password. verify password with auth server. + */ +void +userpasswd(Method *mp) +{ + char key[7]; + char buf[8 + NAMELEN]; + int fd, crfd; + + if(*username == 0 || strcmp(username, "none") == 0){ + strcpy(username, "none"); + outin("user", username, sizeof(username)); + } + crfd = fd = -1; + while(strcmp(username, "none") != 0 && strcmp(mp->name, "local") != 0){ + getpasswd(password, sizeof password); + if(!passtokey(key, password, strlen(password))){ + print("bad password; try again\n"); + continue; + } + fd = open("#c/key", OWRITE); + if(fd < 0) + fatal("can't open #c/key; please reboot"); + if(write(fd, key, 7) != 7) + fatal("can't write #c/key; please reboot"); + close(fd); + crfd = open("#c/crypt", ORDWR); + if(crfd < 0) + fatal("can't open crypt file"); + write(crfd, "E", 1); + fd = (*mp->auth)(); + if(fd < 0){ + warning("password not checked!"); + break; + } + strncpy(buf+8, username, NAMELEN); + if(read(fd, buf, 8) != 8 + || write(crfd, buf, 8) != 8 + || read(crfd, buf, 8) != 8 + || write(fd, buf, 8 + NAMELEN) != 8 + NAMELEN){ + warning("password not checked!"); + break; + } + if(read(fd, buf, 2) == 2 && buf[0]=='O' && buf[1]=='K') + break; + close(fd); + outin("user", username, sizeof(username)); + } + close(fd); + close(crfd); + + /* set user now that we're sure */ + fd = open("#c/user", OWRITE|OTRUNC); + if(fd >= 0){ + if(write(fd, username, strlen(username)) < 0) + warning("write user name"); + close(fd); + }else + warning("open #c/user"); +} diff --git a/port/devcons.c b/port/devcons.c index 341b5155204071e7e1aba06f543bfe5f764400b8..640b74134d19bc1df57099bc1e757e693ebe3b39 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -379,7 +379,7 @@ int readnum(ulong off, char *buf, ulong n, ulong val, int size) { char tmp[64]; - Op op = (Op){ tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG }; + Op op = { tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG }; numbconv(&op, 10); tmp[size-1] = ' '; diff --git a/port/devmnt.c b/port/devmnt.c index 7e529e38fba5894cc4aac7d1a775573a12daefed..e0f329d4bc944f0bbccb165ffcfa224f649f42e4 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -160,12 +160,11 @@ mntattach(char *muxattach) m->blocksize = MAXFDATA; switch(devchar[m->c->type]) { - case 'H': /* Hotrod */ - case '3': /* BIT3 */ - m->mux = 1; - break; default: m->mux = 0; + case 'H': /* Cyclone */ + m->mux = 1; + break; } incref(m->c); unlock(m); diff --git a/port/page.c b/port/page.c index 735c1fda947e08d830b803a746a8ce839609e35b..c9a3caacaa96658ef0c31bbb7ec4f18a7e07694a 100644 --- a/port/page.c +++ b/port/page.c @@ -97,7 +97,7 @@ addsplit(Region *r, ulong start, ulong end) * Called to allocate permanent data structures, before calling pageinit(). * We assume all of text+data+bss is in the first memory bank. * - * alignment is in number of bytes. It pretains both to the start and + * alignment is in number of bytes. It pertains both to the start and * end of the allocated memory. * * If crevasse is specified, no allocation can span an address that is @@ -195,6 +195,7 @@ pageinit(void) ulong i, vmem, pmem, hw, hr; Page *p; +print("addr0 %lux addr1 %lux\n", palloc.addr0, palloc.addr1); /* * calculate an upper bound to the number of pages structures * we'll need (np). diff --git a/power/devhotrod.c b/power/devhotrod.c index 8a138c786dc86649fa7599b92a092c2372efb222..a3307768c62131520329ebb2d43d81d76cb2954a 100644 --- a/power/devhotrod.c +++ b/power/devhotrod.c @@ -423,9 +423,7 @@ hotrodintr(int vec) if(h->ri >= NRQ) h->ri = 0; hm->intr = 1; - if(hm->abort) - print("abort wakeup\n"); - else + if(!hm->abort) wakeup(&hm->r); } }