diff options
author | Alex Musolino <alex@musolino.id.au> | 2020-12-15 20:55:41 +1030 |
---|---|---|
committer | Alex Musolino <alex@musolino.id.au> | 2020-12-15 20:55:41 +1030 |
commit | 3749e92cdb88a157f99c0709a264bd508603be9b (patch) | |
tree | 49ce703965ba4114490729c5aeabd9ba120d9b78 /sys/src/cmd | |
parent | 404c901f299c4d93cb159a3c44c2977a25408319 (diff) | |
parent | 32291b52bcbd6976051acff1692b571e321ac859 (diff) |
merge
Diffstat (limited to 'sys/src/cmd')
29 files changed, 1342 insertions, 1106 deletions
diff --git a/sys/src/cmd/aux/kbdfs/kbdfs.c b/sys/src/cmd/aux/kbdfs/kbdfs.c index 8a57b52fc..a7a5a6966 100644 --- a/sys/src/cmd/aux/kbdfs/kbdfs.c +++ b/sys/src/cmd/aux/kbdfs/kbdfs.c @@ -179,7 +179,7 @@ Rune kbtabesc1[Nscan] = [0x40] 0, 0, 0, 0, 0, 0, Kbreak, Khome, [0x48] Kup, Kpgup, 0, Kleft, 0, Kright, 0, Kend, [0x50] Kdown, Kpgdown,Kins, Kdel, 0, 0, 0, 0, -[0x58] 0, 0, 0, 0, 0, 0, 0, 0, +[0x58] 0, 0, 0, Kmod4, 0, 0, 0, 0, [0x60] 0, 0, 0, 0, 0, 0, 0, 0, [0x68] 0, 0, 0, 0, 0, 0, 0, 0, [0x70] 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/sys/src/cmd/aux/statusbar.c b/sys/src/cmd/aux/statusbar.c index 02d85176f..6d2db3295 100644 --- a/sys/src/cmd/aux/statusbar.c +++ b/sys/src/cmd/aux/statusbar.c @@ -21,10 +21,10 @@ initcolor(void) text = display->black; light = allocimagemix(display, DPalegreen, DWhite); dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen); + if(light == nil || dark == nil) sysfatal("initcolor: %r"); } Rectangle rbar; -Point ptext; vlong n, d; int last; int lastp = -1; @@ -75,7 +75,7 @@ drawbar(void) if(lastp != p){ sprint(buf, "%3d%%", p); - stringbg(screen, addpt(screen->r.min, Pt(Dx(rbar)-30, 4)), text, ZP, display->defaultfont, buf, light, ZP); + stringbg(screen, Pt(screen->r.max.x-4-stringwidth(display->defaultfont, buf), screen->r.min.y+4), text, ZP, display->defaultfont, buf, light, ZP); lastp = p; } @@ -94,24 +94,13 @@ drawbar(void) void eresized(int new) { - Point p, q; - Rectangle r; - if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); - r = screen->r; - draw(screen, r, light, nil, ZP); - p = string(screen, addpt(r.min, Pt(4,4)), text, ZP, - display->defaultfont, title); - - p.x = r.min.x+4; - p.y += display->defaultfont->height+4; - - q = subpt(r.max, Pt(4,4)); - rbar = Rpt(p, q); - - ptext = Pt(r.max.x-4-stringwidth(display->defaultfont, "100%"), r.min.x+4); + draw(screen, screen->r, light, nil, ZP); + if(title) string(screen, addpt(screen->r.min, Pt(4,4)), text, ZP, font, title); + rbar = insetrect(screen->r, 4); + rbar.min.y += font->height + 4; border(screen, rbar, -2, dark, ZP); last = 0; lastp = -1; @@ -163,7 +152,7 @@ bar(Biobuf *b) void usage(void) { - fprint(2, "usage: aux/statusbar [-kt] [-w minx,miny,maxx,maxy] 'title'\n"); + fprint(2, "usage: %s [-kt] [-w minx,miny,maxx,maxy] [title]\n", argv0); exits("usage"); } @@ -190,11 +179,14 @@ main(int argc, char **argv) usage(); }ARGEND; - if(argc != 1) + switch(argc){ + default: usage(); - - title = argv[0]; - + case 1: + title = argv[0]; + case 0: + break; + } lfd = dup(0, -1); while(q = strchr(p, ',')) @@ -204,7 +196,7 @@ main(int argc, char **argv) textmode = 1; rbar = Rect(0, 0, 60, 1); }else{ - if(initdraw(0, 0, title) < 0) + if(initdraw(0, 0, title ? title : argv0) < 0) exits("initdraw"); initcolor(); einit(Emouse|Ekeyboard); diff --git a/sys/src/cmd/aux/statusmsg.c b/sys/src/cmd/aux/statusmsg.c index 1133a090a..fa2f4790b 100644 --- a/sys/src/cmd/aux/statusmsg.c +++ b/sys/src/cmd/aux/statusmsg.c @@ -22,6 +22,7 @@ initcolor(void) { text = display->black; light = allocimagemix(display, DPalegreen, DWhite); + if(light == nil) sysfatal("initcolor: %r"); } void @@ -136,7 +137,6 @@ main(int argc, char **argv) usage(); case 1: title = argv[0]; - break; case 0: break; } @@ -153,7 +153,7 @@ main(int argc, char **argv) if((bout = Bfdopen(1, OWRITE)) == nil) sysfatal("Bfdopen: %r"); }else{ - if(initdraw(0, 0, title) < 0) + if(initdraw(0, 0, title ? title : argv0) < 0) sysfatal("initdraw: %r"); initcolor(); einit(Emouse|Ekeyboard); diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c index 98080347d..3fb3a6d5e 100644 --- a/sys/src/cmd/cpu.c +++ b/sys/src/cmd/cpu.c @@ -37,7 +37,7 @@ char *patternfile; char *origargs; char *srvname = "ncpu"; -char *exportfs = "/bin/exportfs"; +char *exportfs = "/bin/oexportfs"; char *ealgs = "rc4_256 sha1"; /* message size for exportfs; may be larger so we can do big graphics in CPU window */ diff --git a/sys/src/cmd/exportfs/exportfs.c b/sys/src/cmd/exportfs/exportfs.c index 275151a6c..b17cec499 100644 --- a/sys/src/cmd/exportfs/exportfs.c +++ b/sys/src/cmd/exportfs/exportfs.c @@ -1,135 +1,44 @@ -/* - * exportfs - Export a plan 9 name space across a network - */ #include <u.h> #include <libc.h> -#include <auth.h> #include <fcall.h> -#include <libsec.h> #define Extern #include "exportfs.h" -#define QIDPATH ((1LL<<48)-1) -vlong newqid = 0; - -enum { - Encnone, - Encssl, - Enctls, -}; - -void (*fcalls[])(Fsrpc*) = -{ - [Tversion] Xversion, - [Tauth] Xauth, - [Tflush] Xflush, - [Tattach] Xattach, - [Twalk] Xwalk, - [Topen] slave, - [Tcreate] Xcreate, - [Tclunk] Xclunk, - [Tread] slave, - [Twrite] slave, - [Tremove] Xremove, - [Tstat] Xstat, - [Twstat] Xwstat, -}; - -/* accounting and debugging counters */ -int filecnt; -int freecnt; -int qidcnt; -int qfreecnt; -int ncollision; - int srvfd = -1; -int nonone = 1; -char *filterp; -char *ealgs = "rc4_256 sha1"; -char *aanfilter = "/bin/aan"; -int encproto = Encnone; int readonly; -static void mksecret(char *, uchar *); -static char *anstring = "tcp!*!0"; - -char *netdir = "", *local = "", *remote = ""; - -void filter(int, char *, char *); - void usage(void) { - fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] " - "[-S srvfile] [-e 'crypt hash'] [-P exclusion-file] " - "[-A announce-string] [-B address]\n", argv0); + fprint(2, "usage: %s [-dsR] [-f dbgfile] [-m msize] [-r root] " + "[-S srvfile] [-P exclusion-file]\n", argv0); fatal("usage"); } -static void -noteconn(int fd) -{ - NetConnInfo *nci; - - nci = getnetconninfo(nil, fd); - if(nci == nil) - return; - netdir = estrdup(nci->dir); - local = estrdup(nci->lsys); - remote = estrdup(nci->rsys); - freenetconninfo(nci); -} - void main(int argc, char **argv) { - char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile; - char *dbfile, *srv, *na, *nsfile, *keyspec; - int doauth, n, fd; - AuthInfo *ai; - Fsrpc *r; + char *dbfile, *srv, *srvfdfile; + int n; dbfile = "/tmp/exportdb"; srv = nil; srvfd = -1; srvfdfile = nil; - na = nil; - nsfile = nil; - keyspec = ""; - doauth = 0; - ai = nil; ARGBEGIN{ - case 'a': - doauth = 1; - break; - case 'd': dbg++; break; - case 'e': - ealgs = EARGF(usage()); - if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) - ealgs = nil; - break; - case 'f': dbfile = EARGF(usage()); break; - case 'k': - keyspec = EARGF(usage()); - break; - case 'm': messagesize = strtoul(EARGF(usage()), nil, 0); break; - case 'n': - nonone = 0; - break; - case 'r': srv = EARGF(usage()); break; @@ -138,22 +47,10 @@ main(int argc, char **argv) srv = "/"; break; - case 'A': - anstring = EARGF(usage()); - break; - - case 'B': - na = EARGF(usage()); - break; - case 'F': /* accepted but ignored, for backwards compatibility */ break; - case 'N': - nsfile = EARGF(usage()); - break; - case 'P': patternfile = EARGF(usage()); break; @@ -173,52 +70,15 @@ main(int argc, char **argv) }ARGEND USED(argc, argv); - if(na == nil && doauth){ - /* - * We use p9any so we don't have to visit this code again, with the - * cost that this code is incompatible with the old world, which - * requires p9sk2. (The two differ in who talks first, so compatibility - * is awkward.) - */ - ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec); - if(ai == nil) - fatal("auth_proxy: %r"); - if(nonone && strcmp(ai->cuid, "none") == 0) - fatal("exportfs by none disallowed"); - if(auth_chuid(ai, nsfile) < 0) - fatal("auth_chuid: %r"); - else { /* chown network connection */ - Dir nd; - nulldir(&nd); - nd.mode = 0660; - nd.uid = ai->cuid; - dirfwstat(0, &nd); - } - putenv("service", "exportfs"); - } - if(srvfdfile != nil){ + if(srv != nil){ + fprint(2, "exportfs: -S cannot be used with -r or -s\n"); + usage(); + } if((srvfd = open(srvfdfile, ORDWR)) < 0) fatal("open %s: %r", srvfdfile); - } - - if(na != nil){ - if(srv == nil) - fatal("-B requires -s"); - - local = "me"; - remote = na; - if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) - fatal("can't dial %s: %r", na); - - ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); - if(ai == nil) - fatal("%r: %s", na); - - dup(fd, 0); - dup(fd, 1); - close(fd); - } + } else if(srv == nil) + usage(); exclusions(); @@ -228,11 +88,6 @@ main(int argc, char **argv) close(n); } - if(srvfd >= 0 && srv != nil){ - fprint(2, "exportfs: -S cannot be used with -r or -s\n"); - usage(); - } - DEBUG(DFD, "exportfs: started\n"); rfork(RFNOTEG|RFREND); @@ -246,695 +101,18 @@ main(int argc, char **argv) fmtinstall('F', fcallfmt); - /* - * Get tree to serve from network connection, - * check we can get there and ack the connection - */ - if(srvfd != -1) { - /* do nothing */ - } - else if(srv != nil) { + if(srvfd == -1) { if(chdir(srv) < 0) { + char ebuf[ERRMAX]; ebuf[0] = '\0'; errstr(ebuf, sizeof ebuf); - r = getsbuf(); - r->work.tag = NOTAG; - r->work.fid = NOFID; - r->work.type = Rerror; - r->work.ename = ebuf; - n = convS2M(&r->work, r->buf, messagesize); - write(0, r->buf, n); DEBUG(DFD, "chdir(\"%s\"): %s\n", srv, ebuf); - exits(ebuf); + mounterror(ebuf); } DEBUG(DFD, "invoked as server for %s", srv); - strncpy(buf, srv, sizeof buf); - } - else { - noteconn(0); - buf[0] = 0; - n = read(0, buf, sizeof(buf)-1); - if(n < 0) { - errstr(buf, sizeof buf); - fprint(0, "read(0): %s\n", buf); - DEBUG(DFD, "read(0): %s\n", buf); - exits(buf); - } - buf[n] = 0; - if(chdir(buf) < 0) { - errstr(ebuf, sizeof ebuf); - fprint(0, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); - DEBUG(DFD, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); - exits(ebuf); - } } DEBUG(DFD, "\niniting root\n"); initroot(); - - DEBUG(DFD, "exportfs: %s\n", buf); - - if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2) - fatal("open ack write"); - - ini = initial; - n = readn(0, initial, sizeof(initial)); - if(n == 0) - fatal(nil); /* port scan or spurious open/close on exported /srv file (unmount) */ - if(n < sizeof(initial)) - fatal("can't read initial string: %r"); - - if(memcmp(ini, "impo", 4) == 0) { - char buf[128], *p, *args[3]; - - ini = nil; - p = buf; - for(;;){ - if((n = read(0, p, 1)) < 0) - fatal("can't read impo arguments: %r"); - if(n == 0) - fatal("connection closed while reading arguments"); - if(*p == '\n') - *p = '\0'; - if(*p++ == '\0') - break; - if(p >= buf + sizeof(buf)) - fatal("import parameters too long"); - } - - if(tokenize(buf, args, nelem(args)) != 2) - fatal("impo arguments invalid: impo%s...", buf); - - if(strcmp(args[0], "aan") == 0) - filterp = aanfilter; - else if(strcmp(args[0], "nofilter") != 0) - fatal("import filter argument unsupported: %s", args[0]); - - if(strcmp(args[1], "ssl") == 0) - encproto = Encssl; - else if(strcmp(args[1], "tls") == 0) - encproto = Enctls; - else if(strcmp(args[1], "clear") != 0) - fatal("import encryption proto unsupported: %s", args[1]); - - if(encproto == Enctls) - fatal("%s: tls has not yet been implemented", argv[0]); - } - - if(encproto != Encnone && ealgs != nil && ai != nil) { - uchar key[16], digest[SHA1dlen]; - char fromclientsecret[21]; - char fromserversecret[21]; - int i; - - if(ai->nsecret < 8) - fatal("secret too small for ssl"); - memmove(key+4, ai->secret, 8); - - /* exchange random numbers */ - srand(truerand()); - for(i = 0; i < 4; i++) - key[i+12] = rand(); - - if(ini != nil) - fatal("Protocol botch: old import"); - if(readn(0, key, 4) != 4) - fatal("can't read key part; %r"); - - if(write(0, key+12, 4) != 4) - fatal("can't write key part; %r"); - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(fromclientsecret, digest); - mksecret(fromserversecret, digest+10); - - if(filterp != nil) - filter(0, filterp, na); - - switch(encproto) { - case Encssl: - fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil); - if(fd < 0) - fatal("can't establish ssl connection: %r"); - if(fd != 0){ - dup(fd, 0); - close(fd); - } - break; - case Enctls: - default: - fatal("Unsupported encryption protocol"); - } - } - else if(filterp != nil) { - if(ini != nil) - fatal("Protocol botch: don't know how to deal with this"); - filter(0, filterp, na); - } - dup(0, 1); - - if(ai != nil) - auth_freeAI(ai); - - if(ini != nil){ - r = getsbuf(); - memmove(r->buf, ini, BIT32SZ); - n = GBIT32(r->buf); - if(n <= BIT32SZ || n > messagesize) - fatal("bad length in 9P2000 message header"); - n -= BIT32SZ; - if(readn(0, r->buf+BIT32SZ, n) != n) - fatal(nil); - n += BIT32SZ; - goto Message; - } - - /* - * Start serving file requests from the network - */ - for(;;) { - r = getsbuf(); - n = read9pmsg(0, r->buf, messagesize); - if(n <= 0) - fatal(nil); - Message: - if(convM2S(r->buf, n, &r->work) != n) - fatal("convM2S format error"); - - DEBUG(DFD, "%F\n", &r->work); - (fcalls[r->work.type])(r); - } -} - -void -reply(Fcall *r, Fcall *t, char *err) -{ - uchar *data; - int n; - - t->tag = r->tag; - t->fid = r->fid; - if(err != nil) { - t->type = Rerror; - t->ename = err; - } - else - t->type = r->type + 1; - - DEBUG(DFD, "\t%F\n", t); - - data = malloc(messagesize); /* not mallocz; no need to clear */ - if(data == nil) - fatal(Enomem); - n = convS2M(t, data, messagesize); - if(write(0, data, n) != n){ - /* not fatal, might have got a note due to flush */ - fprint(2, "exportfs: short write in reply: %r\n"); - } - free(data); -} - -Fid * -getfid(int nr) -{ - Fid *f; - - for(f = fidhash(nr); f != nil; f = f->next) - if(f->nr == nr) - return f; - - return nil; -} - -int -freefid(int nr) -{ - Fid *f, **l; - char buf[128]; - - l = &fidhash(nr); - for(f = *l; f != nil; f = f->next) { - if(f->nr == nr) { - if(f->mid) { - snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid); - unmount(0, buf); - psmap[f->mid] = 0; - } - if(f->f != nil) { - freefile(f->f); - f->f = nil; - } - if(f->dir != nil){ - free(f->dir); - f->dir = nil; - } - *l = f->next; - f->next = fidfree; - fidfree = f; - return 1; - } - l = &f->next; - } - - return 0; -} - -Fid * -newfid(int nr) -{ - Fid *new, **l; - int i; - - l = &fidhash(nr); - for(new = *l; new != nil; new = new->next) - if(new->nr == nr) - return nil; - - if(fidfree == nil) { - fidfree = emallocz(sizeof(Fid) * Fidchunk); - - for(i = 0; i < Fidchunk-1; i++) - fidfree[i].next = &fidfree[i+1]; - - fidfree[Fidchunk-1].next = nil; - } - - new = fidfree; - fidfree = new->next; - - memset(new, 0, sizeof(Fid)); - new->next = *l; - *l = new; - new->nr = nr; - new->fid = -1; - new->mid = 0; - - return new; -} - -static struct { - Lock; - Fsrpc *free; - - /* statistics */ - int nalloc; - int nfree; -} sbufalloc; - -Fsrpc * -getsbuf(void) -{ - Fsrpc *w; - - lock(&sbufalloc); - w = sbufalloc.free; - if(w != nil){ - sbufalloc.free = w->next; - w->next = nil; - sbufalloc.nfree--; - unlock(&sbufalloc); - } else { - sbufalloc.nalloc++; - unlock(&sbufalloc); - w = emallocz(sizeof(*w) + messagesize); - } - w->flushtag = NOTAG; - return w; -} - -void -putsbuf(Fsrpc *w) -{ - w->flushtag = NOTAG; - lock(&sbufalloc); - w->next = sbufalloc.free; - sbufalloc.free = w; - sbufalloc.nfree++; - unlock(&sbufalloc); -} - -void -freefile(File *f) -{ - File *parent, *child; - - while(--f->ref == 0){ - freecnt++; - DEBUG(DFD, "free %s\n", f->name); - /* delete from parent */ - parent = f->parent; - if(parent->child == f) - parent->child = f->childlist; - else{ - for(child = parent->child; child->childlist != f; child = child->childlist) { - if(child->childlist == nil) - fatal("bad child list"); - } - child->childlist = f->childlist; - } - freeqid(f->qidt); - free(f->name); - free(f); - f = parent; - } -} - -File * -file(File *parent, char *name) -{ - Dir *dir; - char *path; - File *f; - - DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); - - path = makepath(parent, name); - if(patternfile != nil && excludefile(path)){ - free(path); - return nil; - } - dir = dirstat(path); - free(path); - if(dir == nil) - return nil; - - for(f = parent->child; f != nil; f = f->childlist) - if(strcmp(name, f->name) == 0) - break; - - if(f == nil){ - f = emallocz(sizeof(File)); - f->name = estrdup(name); - - f->parent = parent; - f->childlist = parent->child; - parent->child = f; - parent->ref++; - f->ref = 0; - filecnt++; - } - f->ref++; - f->qid.type = dir->qid.type; - f->qid.vers = dir->qid.vers; - f->qidt = uniqueqid(dir); - f->qid.path = f->qidt->uniqpath; - - f->inval = 0; - - free(dir); - - return f; -} - -void -initroot(void) -{ - Dir *dir; - - root = emallocz(sizeof(File)); - root->name = estrdup("."); - - dir = dirstat(root->name); - if(dir == nil) - fatal("root stat"); - - root->ref = 1; - root->qid.vers = dir->qid.vers; - root->qidt = uniqueqid(dir); - root->qid.path = root->qidt->uniqpath; - root->qid.type = QTDIR; - free(dir); - - psmpt = emallocz(sizeof(File)); - psmpt->name = estrdup("/"); - - dir = dirstat(psmpt->name); - if(dir == nil) - return; - - psmpt->ref = 1; - psmpt->qid.vers = dir->qid.vers; - psmpt->qidt = uniqueqid(dir); - psmpt->qid.path = psmpt->qidt->uniqpath; - free(dir); - - psmpt = file(psmpt, "mnt"); - if(psmpt == nil) - return; - psmpt = file(psmpt, "exportfs"); -} - -char* -makepath(File *p, char *name) -{ - int i, n; - char *c, *s, *path, *seg[256]; - - seg[0] = name; - n = strlen(name)+2; - for(i = 1; i < 256 && p; i++, p = p->parent){ - seg[i] = p->name; - n += strlen(p->name)+1; - } - path = emallocz(n); - s = path; - - while(i--) { - for(c = seg[i]; *c; c++) - *s++ = *c; - *s++ = '/'; - } - while(s[-1] == '/') - s--; - *s = '\0'; - - return path; -} - -int -qidhash(vlong path) -{ - int h, n; - - h = 0; - for(n=0; n<64; n+=Nqidbits){ - h ^= path; - path >>= Nqidbits; - } - return h & (Nqidtab-1); -} - -void -freeqid(Qidtab *q) -{ - ulong h; - Qidtab *l; - - if(--q->ref) - return; - qfreecnt++; - h = qidhash(q->path); - if(qidtab[h] == q) - qidtab[h] = q->next; - else{ - for(l=qidtab[h]; l->next!=q; l=l->next) - if(l->next == nil) - fatal("bad qid list"); - l->next = q->next; - } - free(q); -} - -Qidtab* -qidlookup(Dir *d) -{ - ulong h; - Qidtab *q; - - h = qidhash(d->qid.path); - for(q=qidtab[h]; q!=nil; q=q->next) - if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) - return q; - return nil; -} - -int -qidexists(vlong path) -{ - int h; - Qidtab *q; - - for(h=0; h<Nqidtab; h++) - for(q=qidtab[h]; q!=nil; q=q->next) - if(q->uniqpath == path) - return 1; - return 0; -} - -Qidtab* -uniqueqid(Dir *d) -{ - ulong h; - vlong path; - Qidtab *q; - - q = qidlookup(d); - if(q != nil){ - q->ref++; - return q; - } - path = d->qid.path; - while(qidexists(path)){ - DEBUG(DFD, "collision on %s\n", d->name); - /* collision: find a new one */ - ncollision++; - path &= QIDPATH; - ++newqid; - if(newqid >= (1<<16)){ - DEBUG(DFD, "collision wraparound\n"); - newqid = 1; - } - path |= newqid<<48; - DEBUG(DFD, "assign qid %.16llux\n", path); - } - qidcnt++; - q = emallocz(sizeof(Qidtab)); - q->ref = 1; - q->type = d->type; - q->dev = d->dev; - q->path = d->qid.path; - q->uniqpath = path; - h = qidhash(d->qid.path); - q->next = qidtab[h]; - qidtab[h] = q; - return q; -} - -void -fatal(char *s, ...) -{ - char buf[ERRMAX]; - va_list arg; - Proc *m; - - if(s != nil) { - va_start(arg, s); - vsnprint(buf, ERRMAX, s, arg); - va_end(arg); - } - - /* Clear away the slave children */ - for(m = Proclist; m != nil; m = m->next) - postnote(PNPROC, m->pid, "kill"); - - if(s != nil) { - DEBUG(DFD, "%s\n", buf); - sysfatal("%s", buf); /* caution: buf could contain '%' */ - } else - exits(nil); -} - -void* -emallocz(uint n) -{ - void *p; - - p = mallocz(n, 1); - if(p == nil) - fatal(Enomem); - setmalloctag(p, getcallerpc(&n)); - return p; -} - -char* -estrdup(char *s) -{ - char *t; - - t = strdup(s); - if(t == nil) - fatal(Enomem); - setmalloctag(t, getcallerpc(&s)); - return t; -} - -void -filter(int fd, char *cmd, char *host) -{ - char addr[128], buf[256], *s, *file, *argv[16]; - int lfd, p[2], len, argc; - - if(host == nil){ - /* Get a free port and post it to the client. */ - if (announce(anstring, addr) < 0) - fatal("filter: Cannot announce %s: %r", anstring); - - snprint(buf, sizeof(buf), "%s/local", addr); - if ((lfd = open(buf, OREAD)) < 0) - fatal("filter: Cannot open %s: %r", buf); - if ((len = read(lfd, buf, sizeof buf - 1)) < 0) - fatal("filter: Cannot read %s: %r", buf); - close(lfd); - buf[len] = '\0'; - if ((s = strchr(buf, '\n')) != nil) - len = s - buf; - if (write(fd, buf, len) != len) - fatal("filter: cannot write port; %r"); - } else { - /* Read address string from connection */ - if ((len = read(fd, buf, sizeof buf - 1)) < 0) - sysfatal("filter: cannot write port; %r"); - buf[len] = '\0'; - - if ((s = strrchr(buf, '!')) == nil) - sysfatal("filter: illegally formatted port %s", buf); - strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); - strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); - } - - DEBUG(DFD, "filter: %s\n", addr); - - snprint(buf, sizeof(buf), "%s", cmd); - argc = tokenize(buf, argv, nelem(argv)-3); - if (argc == 0) - sysfatal("filter: empty command"); - - if(host != nil) - argv[argc++] = "-c"; - argv[argc++] = addr; - argv[argc] = nil; - - file = argv[0]; - if((s = strrchr(argv[0], '/')) != nil) - argv[0] = s+1; - - if(pipe(p) < 0) - sysfatal("pipe: %r"); - - switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) { - case -1: - fatal("filter: rfork; %r\n"); - case 0: - close(fd); - if (dup(p[0], 1) < 0) - fatal("filter: Cannot dup to 1; %r"); - if (dup(p[0], 0) < 0) - fatal("filter: Cannot dup to 0; %r"); - close(p[0]); - close(p[1]); - exec(file, argv); - fatal("filter: exec; %r"); - default: - dup(p[1], fd); - close(p[0]); - close(p[1]); - } -} - -static void -mksecret(char *t, uchar *f) -{ - sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", - f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); + io(); } diff --git a/sys/src/cmd/exportfs/exportfs.h b/sys/src/cmd/exportfs/exportfs.h index b3587fab2..344304b7c 100644 --- a/sys/src/cmd/exportfs/exportfs.h +++ b/sys/src/cmd/exportfs/exportfs.h @@ -112,7 +112,10 @@ void Xwalk(Fsrpc*); void Xwstat(Fsrpc*); void slave(Fsrpc*); +void io(void); void reply(Fcall*, Fcall*, char*); +void mounterror(char*); + Fid *getfid(int); int freefid(int); Fid *newfid(int); diff --git a/sys/src/cmd/exportfs/exportsrv.c b/sys/src/cmd/exportfs/exportsrv.c index a413ed0dc..b7ddd64b5 100644 --- a/sys/src/cmd/exportfs/exportsrv.c +++ b/sys/src/cmd/exportfs/exportsrv.c @@ -5,8 +5,6 @@ #define Extern extern #include "exportfs.h" -extern char *netdir, *local, *remote; - char Ebadfid[] = "Bad fid"; char Enotdir[] = "Not a directory"; char Edupfid[] = "Fid already in use"; @@ -493,12 +491,6 @@ slave(Fsrpc *f) return; case 0: - if (local[0] != '\0') - if (netdir[0] != '\0') - procsetname("%s: %s -> %s", netdir, - local, remote); - else - procsetname("%s -> %s", local, remote); blockingslave(m); _exits(0); diff --git a/sys/src/cmd/exportfs/io.c b/sys/src/cmd/exportfs/io.c new file mode 100644 index 000000000..ad1d7154b --- /dev/null +++ b/sys/src/cmd/exportfs/io.c @@ -0,0 +1,503 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#define Extern +#include "exportfs.h" + +#define QIDPATH ((1LL<<48)-1) +vlong newqid = 0; + +void (*fcalls[])(Fsrpc*) = +{ + [Tversion] Xversion, + [Tauth] Xauth, + [Tflush] Xflush, + [Tattach] Xattach, + [Twalk] Xwalk, + [Topen] slave, + [Tcreate] Xcreate, + [Tclunk] Xclunk, + [Tread] slave, + [Twrite] slave, + [Tremove] Xremove, + [Tstat] Xstat, + [Twstat] Xwstat, +}; + +/* accounting and debugging counters */ +int filecnt; +int freecnt; +int qidcnt; +int qfreecnt; +int ncollision; + + +/* + * Start serving file requests from the network + */ +void +io(void) +{ + Fsrpc *r; + int n; + + for(;;) { + r = getsbuf(); + n = read9pmsg(0, r->buf, messagesize); + if(n <= 0) + fatal(nil); + if(convM2S(r->buf, n, &r->work) != n) + fatal("convM2S format error"); + + DEBUG(DFD, "%F\n", &r->work); + (fcalls[r->work.type])(r); + } +} + +void +reply(Fcall *r, Fcall *t, char *err) +{ + uchar *data; + int n; + + t->tag = r->tag; + t->fid = r->fid; + if(err != nil) { + t->type = Rerror; + t->ename = err; + } + else + t->type = r->type + 1; + + DEBUG(DFD, "\t%F\n", t); + + data = malloc(messagesize); /* not mallocz; no need to clear */ + if(data == nil) + fatal(Enomem); + n = convS2M(t, data, messagesize); + if(write(1, data, n) != n){ + /* not fatal, might have got a note due to flush */ + fprint(2, "exportfs: short write in reply: %r\n"); + } + free(data); +} + +void +mounterror(char *err) +{ + Fsrpc *r; + int n; + + r = getsbuf(); + r->work.tag = NOTAG; + r->work.fid = NOFID; + r->work.type = Rerror; + r->work.ename = err; + n = convS2M(&r->work, r->buf, messagesize); + write(1, r->buf, n); + exits(err); +} + +Fid * +getfid(int nr) +{ + Fid *f; + + for(f = fidhash(nr); f != nil; f = f->next) + if(f->nr == nr) + return f; + + return nil; +} + +int +freefid(int nr) +{ + Fid *f, **l; + char buf[128]; + + l = &fidhash(nr); + for(f = *l; f != nil; f = f->next) { + if(f->nr == nr) { + if(f->mid) { + snprint(buf, sizeof(buf), "/mnt/exportfs/%d", f->mid); + unmount(0, buf); + psmap[f->mid] = 0; + } + if(f->f != nil) { + freefile(f->f); + f->f = nil; + } + if(f->dir != nil){ + free(f->dir); + f->dir = nil; + } + *l = f->next; + f->next = fidfree; + fidfree = f; + return 1; + } + l = &f->next; + } + + return 0; +} + +Fid * +newfid(int nr) +{ + Fid *new, **l; + int i; + + l = &fidhash(nr); + for(new = *l; new != nil; new = new->next) + if(new->nr == nr) + return nil; + + if(fidfree == nil) { + fidfree = emallocz(sizeof(Fid) * Fidchunk); + + for(i = 0; i < Fidchunk-1; i++) + fidfree[i].next = &fidfree[i+1]; + + fidfree[Fidchunk-1].next = nil; + } + + new = fidfree; + fidfree = new->next; + + memset(new, 0, sizeof(Fid)); + new->next = *l; + *l = new; + new->nr = nr; + new->fid = -1; + new->mid = 0; + + return new; +} + +static struct { + Lock; + Fsrpc *free; + + /* statistics */ + int nalloc; + int nfree; +} sbufalloc; + +Fsrpc * +getsbuf(void) +{ + Fsrpc *w; + + lock(&sbufalloc); + w = sbufalloc.free; + if(w != nil){ + sbufalloc.free = w->next; + w->next = nil; + sbufalloc.nfree--; + unlock(&sbufalloc); + } else { + sbufalloc.nalloc++; + unlock(&sbufalloc); + w = emallocz(sizeof(*w) + messagesize); + } + w->flushtag = NOTAG; + return w; +} + +void +putsbuf(Fsrpc *w) +{ + w->flushtag = NOTAG; + lock(&sbufalloc); + w->next = sbufalloc.free; + sbufalloc.free = w; + sbufalloc.nfree++; + unlock(&sbufalloc); +} + +void +freefile(File *f) +{ + File *parent, *child; + + while(--f->ref == 0){ + freecnt++; + DEBUG(DFD, "free %s\n", f->name); + /* delete from parent */ + parent = f->parent; + if(parent->child == f) + parent->child = f->childlist; + else{ + for(child = parent->child; child->childlist != f; child = child->childlist) { + if(child->childlist == nil) + fatal("bad child list"); + } + child->childlist = f->childlist; + } + freeqid(f->qidt); + free(f->name); + free(f); + f = parent; + } +} + +File * +file(File *parent, char *name) +{ + Dir *dir; + char *path; + File *f; + + DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); + + path = makepath(parent, name); + if(patternfile != nil && excludefile(path)){ + free(path); + return nil; + } + dir = dirstat(path); + free(path); + if(dir == nil) + return nil; + + for(f = parent->child; f != nil; f = f->childlist) + if(strcmp(name, f->name) == 0) + break; + + if(f == nil){ + f = emallocz(sizeof(File)); + f->name = estrdup(name); + + f->parent = parent; + f->childlist = parent->child; + parent->child = f; + parent->ref++; + f->ref = 0; + filecnt++; + } + f->ref++; + f->qid.type = dir->qid.type; + f->qid.vers = dir->qid.vers; + f->qidt = uniqueqid(dir); + f->qid.path = f->qidt->uniqpath; + + f->inval = 0; + + free(dir); + + return f; +} + +void +initroot(void) +{ + Dir *dir; + + root = emallocz(sizeof(File)); + root->name = estrdup("."); + + dir = dirstat(root->name); + if(dir == nil) + fatal("root stat"); + + root->ref = 1; + root->qid.vers = dir->qid.vers; + root->qidt = uniqueqid(dir); + root->qid.path = root->qidt->uniqpath; + root->qid.type = QTDIR; + free(dir); + + psmpt = emallocz(sizeof(File)); + psmpt->name = estrdup("/"); + + dir = dirstat(psmpt->name); + if(dir == nil) + return; + + psmpt->ref = 1; + psmpt->qid.vers = dir->qid.vers; + psmpt->qidt = uniqueqid(dir); + psmpt->qid.path = psmpt->qidt->uniqpath; + free(dir); + + psmpt = file(psmpt, "mnt"); + if(psmpt == nil) + return; + psmpt = file(psmpt, "exportfs"); +} + +char* +makepath(File *p, char *name) +{ + int i, n; + char *c, *s, *path, *seg[256]; + + seg[0] = name; + n = strlen(name)+2; + for(i = 1; i < 256 && p; i++, p = p->parent){ + seg[i] = p->name; + n += strlen(p->name)+1; + } + path = emallocz(n); + s = path; + + while(i--) { + for(c = seg[i]; *c; c++) + *s++ = *c; + *s++ = '/'; + } + while(s[-1] == '/') + s--; + *s = '\0'; + + return path; +} + +int +qidhash(vlong path) +{ + int h, n; + + h = 0; + for(n=0; n<64; n+=Nqidbits){ + h ^= path; + path >>= Nqidbits; + } + return h & (Nqidtab-1); +} + +void +freeqid(Qidtab *q) +{ + ulong h; + Qidtab *l; + + if(--q->ref) + return; + qfreecnt++; + h = qidhash(q->path); + if(qidtab[h] == q) + qidtab[h] = q->next; + else{ + for(l=qidtab[h]; l->next!=q; l=l->next) + if(l->next == nil) + fatal("bad qid list"); + l->next = q->next; + } + free(q); +} + +Qidtab* +qidlookup(Dir *d) +{ + ulong h; + Qidtab *q; + + h = qidhash(d->qid.path); + for(q=qidtab[h]; q!=nil; q=q->next) + if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) + return q; + return nil; +} + +int +qidexists(vlong path) +{ + int h; + Qidtab *q; + + for(h=0; h<Nqidtab; h++) + for(q=qidtab[h]; q!=nil; q=q->next) + if(q->uniqpath == path) + return 1; + return 0; +} + +Qidtab* +uniqueqid(Dir *d) +{ + ulong h; + vlong path; + Qidtab *q; + + q = qidlookup(d); + if(q != nil){ + q->ref++; + return q; + } + path = d->qid.path; + while(qidexists(path)){ + DEBUG(DFD, "collision on %s\n", d->name); + /* collision: find a new one */ + ncollision++; + path &= QIDPATH; + ++newqid; + if(newqid >= (1<<16)){ + DEBUG(DFD, "collision wraparound\n"); + newqid = 1; + } + path |= newqid<<48; + DEBUG(DFD, "assign qid %.16llux\n", path); + } + qidcnt++; + q = emallocz(sizeof(Qidtab)); + q->ref = 1; + q->type = d->type; + q->dev = d->dev; + q->path = d->qid.path; + q->uniqpath = path; + h = qidhash(d->qid.path); + q->next = qidtab[h]; + qidtab[h] = q; + return q; +} + +void +fatal(char *s, ...) +{ + char buf[ERRMAX]; + va_list arg; + Proc *m; + + if(s != nil) { + va_start(arg, s); + vsnprint(buf, ERRMAX, s, arg); + va_end(arg); + } + + /* Clear away the slave children */ + for(m = Proclist; m != nil; m = m->next) + postnote(PNPROC, m->pid, "kill"); + + if(s != nil) { + DEBUG(DFD, "%s\n", buf); + sysfatal("%s", buf); /* caution: buf could contain '%' */ + } else + exits(nil); +} + +void* +emallocz(uint n) +{ + void *p; + + p = mallocz(n, 1); + if(p == nil) + fatal(Enomem); + setmalloctag(p, getcallerpc(&n)); + return p; +} + +char* +estrdup(char *s) +{ + char *t; + + t = strdup(s); + if(t == nil) + fatal(Enomem); + setmalloctag(t, getcallerpc(&s)); + return t; +} diff --git a/sys/src/cmd/exportfs/mkfile b/sys/src/cmd/exportfs/mkfile index cf1f51451..df89c4def 100644 --- a/sys/src/cmd/exportfs/mkfile +++ b/sys/src/cmd/exportfs/mkfile @@ -1,10 +1,10 @@ </$objtype/mkfile -TARG=exportfs +TARG=exportfs oexportfs OFILES=\ - exportfs.$O\ exportsrv.$O\ pattern.$O\ + io.$O\ HFILES=exportfs.h\ @@ -15,4 +15,4 @@ UPDATE=\ $HFILES\ ${OFILES:%.$O=%.c}\ -</sys/src/cmd/mkone +</sys/src/cmd/mkmany diff --git a/sys/src/cmd/exportfs/oexportfs.c b/sys/src/cmd/exportfs/oexportfs.c new file mode 100644 index 000000000..c6683a174 --- /dev/null +++ b/sys/src/cmd/exportfs/oexportfs.c @@ -0,0 +1,443 @@ +/* + * oexportfs - legacy exportfs for cpu and import + */ +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <fcall.h> +#include <libsec.h> +#define Extern +#include "exportfs.h" + +enum { + Encnone, + Encssl, + Enctls, +}; + +int srvfd = -1; +int nonone = 1; +char *filterp; +char *ealgs = "rc4_256 sha1"; +char *aanfilter = "/bin/aan"; +int encproto = Encnone; +int readonly; + +static char *anstring = "tcp!*!0"; + +static void +filter(int fd, char *cmd, char *host) +{ + char addr[128], buf[256], *s, *file, *argv[16]; + int lfd, p[2], len, argc; + + if(host == nil){ + /* Get a free port and post it to the client. */ + if (announce(anstring, addr) < 0) + fatal("filter: Cannot announce %s: %r", anstring); + + snprint(buf, sizeof(buf), "%s/local", addr); + if ((lfd = open(buf, OREAD)) < 0) + fatal("filter: Cannot open %s: %r", buf); + if ((len = read(lfd, buf, sizeof buf - 1)) < 0) + fatal("filter: Cannot read %s: %r", buf); + close(lfd); + buf[len] = '\0'; + if ((s = strchr(buf, '\n')) != nil) + len = s - buf; + if (write(fd, buf, len) != len) + fatal("filter: cannot write port; %r"); + } else { + /* Read address string from connection */ + if ((len = read(fd, buf, sizeof buf - 1)) < 0) + sysfatal("filter: cannot write port; %r"); + buf[len] = '\0'; + + if ((s = strrchr(buf, '!')) == nil) + sysfatal("filter: illegally formatted port %s", buf); + strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); + strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); + } + + DEBUG(DFD, "filter: %s\n", addr); + + snprint(buf, sizeof(buf), "%s", cmd); + argc = tokenize(buf, argv, nelem(argv)-3); + if (argc == 0) + sysfatal("filter: empty command"); + + if(host != nil) + argv[argc++] = "-c"; + argv[argc++] = addr; + argv[argc] = nil; + + file = argv[0]; + if((s = strrchr(argv[0], '/')) != nil) + argv[0] = s+1; + + if(pipe(p) < 0) + sysfatal("pipe: %r"); + + switch(rfork(RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND)) { + case -1: + fatal("filter: rfork; %r\n"); + case 0: + close(fd); + if (dup(p[0], 1) < 0) + fatal("filter: Cannot dup to 1; %r"); + if (dup(p[0], 0) < 0) + fatal("filter: Cannot dup to 0; %r"); + close(p[0]); + close(p[1]); + exec(file, argv); + fatal("filter: exec; %r"); + default: + dup(p[1], fd); + close(p[0]); + close(p[1]); + } +} + +static void +mksecret(char *t, uchar *f) +{ + sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", + f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); +} + +void +usage(void) +{ + fprint(2, "usage: %s [-adnsR] [-f dbgfile] [-m msize] [-r root] " + "[-S srvfile] [-e 'crypt hash'] [-P exclusion-file] " + "[-A announce-string] [-B address]\n", argv0); + fatal("usage"); +} + +void +main(int argc, char **argv) +{ + char buf[ERRMAX], ebuf[ERRMAX], initial[4], *ini, *srvfdfile; + char *dbfile, *srv, *na, *nsfile, *keyspec; + int doauth, n, fd; + AuthInfo *ai; + Fsrpc *r; + + dbfile = "/tmp/exportdb"; + srv = nil; + srvfd = -1; + srvfdfile = nil; + na = nil; + nsfile = nil; + keyspec = ""; + doauth = 0; + + ai = nil; + ARGBEGIN{ + case 'a': + doauth = 1; + break; + + case 'd': + dbg++; + break; + + case 'e': + ealgs = EARGF(usage()); + if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) + ealgs = nil; + break; + + case 'f': + dbfile = EARGF(usage()); + break; + + case 'k': + keyspec = EARGF(usage()); + break; + + case 'm': + messagesize = strtoul(EARGF(usage()), nil, 0); + break; + + case 'n': + nonone = 0; + break; + + case 'r': + srv = EARGF(usage()); + break; + + case 's': + srv = "/"; + break; + + case 'A': + anstring = EARGF(usage()); + break; + + case 'B': + na = EARGF(usage()); + break; + + case 'F': + /* accepted but ignored, for backwards compatibility */ + break; + + case 'N': + nsfile = EARGF(usage()); + break; + + case 'P': + patternfile = EARGF(usage()); + break; + + case 'R': + readonly = 1; + break; + + case 'S': + if(srvfdfile != nil) + usage(); + srvfdfile = EARGF(usage()); + break; + + default: + usage(); + }ARGEND + USED(argc, argv); + + if(na == nil && doauth){ + /* + * We use p9any so we don't have to visit this code again, with the + * cost that this code is incompatible with the old world, which + * requires p9sk2. (The two differ in who talks first, so compatibility + * is awkward.) + */ + ai = auth_proxy(0, auth_getkey, "proto=p9any role=server %s", keyspec); + if(ai == nil) + fatal("auth_proxy: %r"); + if(nonone && strcmp(ai->cuid, "none") == 0) + fatal("exportfs by none disallowed"); + if(auth_chuid(ai, nsfile) < 0) + fatal("auth_chuid: %r"); + else { /* chown network connection */ + Dir nd; + nulldir(&nd); + nd.mode = 0660; + nd.uid = ai->cuid; + dirfwstat(0, &nd); + } + putenv("service", "exportfs"); + } + + if(srvfdfile != nil){ + if((srvfd = open(srvfdfile, ORDWR)) < 0) + fatal("open %s: %r", srvfdfile); + } + + if(na != nil){ + if(srv == nil) + fatal("-B requires -s"); + + if((fd = dial(netmkaddr(na, 0, "importfs"), 0, 0, 0)) < 0) + fatal("can't dial %s: %r", na); + + ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); + if(ai == nil) + fatal("%r: %s", na); + + dup(fd, 0); + dup(fd, 1); + close(fd); + } + + exclusions(); + + if(dbg) { + n = create(dbfile, OWRITE|OTRUNC, 0666); + dup(n, DFD); + close(n); + } + + if(srvfd >= 0 && srv != nil){ + fprint(2, "%s: -S cannot be used with -r or -s\n", argv0); + usage(); + } + + DEBUG(DFD, "%s: started\n", argv0); + + rfork(RFNOTEG|RFREND); + + if(messagesize == 0){ + messagesize = iounit(0); + if(messagesize == 0) + messagesize = 8192+IOHDRSZ; + } + fhash = emallocz(sizeof(Fid*)*FHASHSIZE); + + fmtinstall('F', fcallfmt); + + /* + * Get tree to serve from network connection, + * check we can get there and ack the connection + */ + if(srvfd != -1) { + /* do nothing */ + } + else if(srv != nil) { + if(chdir(srv) < 0) { + ebuf[0] = '\0'; + errstr(ebuf, sizeof ebuf); + DEBUG(DFD, "chdir(\"%s\"): %s\n", srv, ebuf); + mounterror(ebuf); + } + DEBUG(DFD, "invoked as server for %s", srv); + strncpy(buf, srv, sizeof buf); + } + else { + buf[0] = 0; + n = read(0, buf, sizeof(buf)-1); + if(n < 0) { + errstr(buf, sizeof buf); + fprint(0, "read(0): %s\n", buf); + DEBUG(DFD, "read(0): %s\n", buf); + exits(buf); + } + buf[n] = 0; + if(chdir(buf) < 0) { + errstr(ebuf, sizeof ebuf); + fprint(0, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); + DEBUG(DFD, "chdir(%d:\"%s\"): %s\n", n, buf, ebuf); + exits(ebuf); + } + } + + DEBUG(DFD, "\niniting root\n"); + initroot(); + + DEBUG(DFD, "%s: %s\n", argv0, buf); + + if(srv == nil && srvfd == -1 && write(0, "OK", 2) != 2) + fatal("open ack write"); + + ini = initial; + n = readn(0, initial, sizeof(initial)); + if(n == 0) + fatal(nil); /* port scan or spurious open/close on exported /srv file (unmount) */ + if(n < sizeof(initial)) + fatal("can't read initial string: %r"); + + if(memcmp(ini, "impo", 4) == 0) { + char buf[128], *p, *args[3]; + + ini = nil; + p = buf; + for(;;){ + if((n = read(0, p, 1)) < 0) + fatal("can't read impo arguments: %r"); + if(n == 0) + fatal("connection closed while reading arguments"); + if(*p == '\n') + *p = '\0'; + if(*p++ == '\0') + break; + if(p >= buf + sizeof(buf)) + fatal("import parameters too long"); + } + + if(tokenize(buf, args, nelem(args)) != 2) + fatal("impo arguments invalid: impo%s...", buf); + + if(strcmp(args[0], "aan") == 0) + filterp = aanfilter; + else if(strcmp(args[0], "nofilter") != 0) + fatal("import filter argument unsupported: %s", args[0]); + + if(strcmp(args[1], "ssl") == 0) + encproto = Encssl; + else if(strcmp(args[1], "tls") == 0) + encproto = Enctls; + else if(strcmp(args[1], "clear") != 0) + fatal("import encryption proto unsupported: %s", args[1]); + + if(encproto == Enctls) + fatal("%s: tls has not yet been implemented", argv[0]); + } + + if(encproto != Encnone && ealgs != nil && ai != nil) { + uchar key[16], digest[SHA1dlen]; + char fromclientsecret[21]; + char fromserversecret[21]; + int i; + + if(ai->nsecret < 8) + fatal("secret too small for ssl"); + memmove(key+4, ai->secret, 8); + + /* exchange random numbers */ + srand(truerand()); + for(i = 0; i < 4; i++) + key[i+12] = rand(); + + if(ini != nil) + fatal("Protocol botch: old import"); + if(readn(0, key, 4) != 4) + fatal("can't read key part; %r"); + + if(write(0, key+12, 4) != 4) + fatal("can't write key part; %r"); + + /* scramble into two secrets */ + sha1(key, sizeof(key), digest, nil); + mksecret(fromclientsecret, digest); + mksecret(fromserversecret, digest+10); + + if(filterp != nil) + filter(0, filterp, na); + + switch(encproto) { + case Encssl: + fd = pushssl(0, ealgs, fromserversecret, fromclientsecret, nil); + if(fd < 0) + fatal("can't establish ssl connection: %r"); + if(fd != 0){ + dup(fd, 0); + close(fd); + } + break; + case Enctls: + default: + fatal("Unsupported encryption protocol"); + } + } + else if(filterp != nil) { + if(ini != nil) + fatal("Protocol botch: don't know how to deal with this"); + filter(0, filterp, na); + } + dup(0, 1); + + if(ai != nil) + auth_freeAI(ai); + + if(ini != nil){ + extern void (*fcalls[])(Fsrpc*); + + r = getsbuf(); + memmove(r->buf, ini, BIT32SZ); + n = GBIT32(r->buf); + if(n <= BIT32SZ || n > messagesize) + fatal("bad length in 9P2000 message header"); + n -= BIT32SZ; + if(readn(0, r->buf+BIT32SZ, n) != n) + fatal(nil); + n += BIT32SZ; + + if(convM2S(r->buf, n, &r->work) != n) + fatal("convM2S format error"); + DEBUG(DFD, "%F\n", &r->work); + (fcalls[r->work.type])(r); + } + io(); +} diff --git a/sys/src/cmd/iostats.c b/sys/src/cmd/iostats.c index e61a7ff94..421f531a9 100644 --- a/sys/src/cmd/iostats.c +++ b/sys/src/cmd/iostats.c @@ -354,6 +354,7 @@ main(int argc, char **argv) sysfatal("fork: %r"); case 0: dup(efd[0], 0); + dup(efd[0], 1); close(efd[0]); close(efd[1]); close(pfd[1]); diff --git a/sys/src/cmd/nusb/kb/kb.c b/sys/src/cmd/nusb/kb/kb.c index 7b9ed9f2c..e00c85b99 100644 --- a/sys/src/cmd/nusb/kb/kb.c +++ b/sys/src/cmd/nusb/kb/kb.c @@ -637,7 +637,7 @@ hidparse(int t, int f, int g[], int l[], int, void *a) s->h = v; break; - case 0x0D0051: /* Conteact identifier */ + case 0x0D0051: /* Contact identifier */ s->id = v; break; @@ -684,7 +684,7 @@ readerproc(void* a) { char err[ERRMAX], mbuf[80]; uchar lastk[64], uk, dk; - int i, c, nerrs, lastb, nlastk; + int i, c, nerrs, bpress, lastb, nlastk; int abs, x, y, z, b; Hidreport p; Hidslot lasts[nelem(p.s)], *s, *l; @@ -774,7 +774,7 @@ readerproc(void* a) continue; /* combine all the slots */ - abs = x = y = z = b = 0; + bpress = abs = x = y = z = b = 0; for(i=0; i<p.ns; *l = *s, i++){ s = &p.s[i]; @@ -785,7 +785,7 @@ readerproc(void* a) if(l == &lasts[nelem(lasts)-1] || !l->valid) *l = *s; - /* convet absolute z to relative */ + /* convert absolute z to relative */ z += s->z; if(s->abs & 4) z -= l->z; @@ -808,6 +808,7 @@ readerproc(void* a) b |= 2; if(s->b & 2) b |= 4; + bpress |= s->m; /* X/Y are absolute? */ if((s->abs & 3) == 3){ @@ -825,7 +826,9 @@ readerproc(void* a) y += s->y; } } - + + if(bpress == 0) + b = lastb & 7; if(z != 0) b |= z > 0 ? 8 : 16; diff --git a/sys/src/cmd/ptrap.c b/sys/src/cmd/ptrap.c index 7cf60f7d4..dae3c088d 100644 --- a/sys/src/cmd/ptrap.c +++ b/sys/src/cmd/ptrap.c @@ -8,6 +8,7 @@ typedef struct IOProc IOProc; typedef struct PFilter PFilter; +typedef struct FAttr FAttr; typedef struct PFid PFid; struct IOProc { @@ -27,11 +28,19 @@ struct PFid { }; Qid rootqid = {.type QTDIR}; +struct FAttr { + char *name; + Reprog *filt; + int invert; + FAttr *next; +}; + struct PFilter { char *name; Reprog *filt; - PFilter *next; int invert; + FAttr *attr; + PFilter *next; }; PFilter *filters; @@ -162,12 +171,32 @@ ptrapopen(Req *r) } static int +filter(PFilter *f, Plumbmsg *pm) +{ + FAttr *a; + char *value; + + if(!(regexec(f->filt, pm->data, nil, 0) ^ f->invert)) + return 0; + for(a = f->attr; a; a = a->next){ + value = plumblookup(pm->attr, a->name); + if(value == nil) + return 0; + if(!(regexec(a->filt, value, nil, 0) ^ f->attr->invert)) + return 0; + } + return 1; +} + +static int filterread(Req *r, PFid *pf) { int rc, len, more; char *buf; Plumbmsg *pm; + PFilter *f; + f = pf->filter; for(;;){ if(pf->msg != nil){ rc = r->ifcall.count; @@ -194,7 +223,7 @@ filterread(Req *r, PFid *pf) len += rc; } free(buf); - if(regexec(pf->filter->filt, pm->data, nil, 0) ^ pf->filter->invert){ + if(filter(f, pm)){ pf->msg = plumbpack(pm, &pf->msgn); pf->msgp = 0; } @@ -341,7 +370,7 @@ Srv ptrapsrv = { void usage(void) { - fprint(2, "usage: %s port regex [ port regex ... ]\n", argv0); + fprint(2, "usage: %s port regex [ +attr regex ... ] ...\n", argv0); exits("usage"); } @@ -349,6 +378,7 @@ void threadmain(int argc, char **argv) { PFilter *f; + FAttr *fa; char *p; int i; @@ -357,19 +387,33 @@ threadmain(int argc, char **argv) }ARGEND; if(argc == 0 || argc % 2) usage(); - for(i = 0; i < argc; i += 2){ + for(i = 0; i+1 < argc;){ + p = argv[i]; f = emalloc9p(sizeof(PFilter)); - f->name = strdup(argv[i]); + f->name = estrdup9p(p); p = argv[i+1]; - if(*p == '!'){ + if(p[0] == '!'){ p++; f->invert = 1; } - f->filt = regcomp(p); - if(f->filt == nil) - sysfatal("%r"); + if((f->filt = regcomp(p)) == nil) + sysfatal("regcomp: %r"); f->next = filters; filters = f; + for(i += 2; p = argv[i], i+1 < argc && p[0] == '+'; i += 2){ + p++; + fa = emalloc9p(sizeof(FAttr)); + fa->name = estrdup9p(p); + p = argv[i+1]; + if(p[0] == '!'){ + p++; + fa->invert = 1; + } + if((fa->filt = regcomp(p)) == nil) + sysfatal("regcomp: %r"); + fa->next = f->attr; + f->attr = fa; + } } threadpostmountsrv(&ptrapsrv, nil, "/mnt/plumb", MREPL | MCREATE); diff --git a/sys/src/cmd/rio/fsys.c b/sys/src/cmd/rio/fsys.c index 1562f71e8..be81a1d57 100644 --- a/sys/src/cmd/rio/fsys.c +++ b/sys/src/cmd/rio/fsys.c @@ -118,37 +118,27 @@ cexecpipe(int *p0, int *p1) Filsys* filsysinit(Channel *cxfidalloc) { - int n, fd, pid, p0; + int p0; Filsys *fs; Channel *c; - char buf[128]; fs = emalloc(sizeof(Filsys)); if(cexecpipe(&fs->cfd, &fs->sfd) < 0) goto Rescue; fmtinstall('F', fcallfmt); clockfd = open("/dev/time", OREAD|OCEXEC); - fd = open("/dev/user", OREAD); - strcpy(buf, "Jean-Paul_Belmondo"); - if(fd >= 0){ - n = read(fd, buf, sizeof buf-1); - if(n > 0) - buf[n] = 0; - close(fd); - } - fs->user = estrdup(buf); + fs->user = getuser(); fs->csyncflush = chancreate(sizeof(int), 0); if(fs->csyncflush == nil) error("chancreate syncflush"); fs->cxfidalloc = cxfidalloc; - pid = getpid(); /* * Create and post wctl pipe */ if(cexecpipe(&p0, &wctlfd) < 0) goto Rescue; - snprint(srvwctl, sizeof(srvwctl), "/srv/riowctl.%s.%d", fs->user, pid); + snprint(srvwctl, sizeof(srvwctl), "/srv/riowctl.%s.%lud", fs->user, (ulong)getpid()); post(srvwctl, "wctl", p0); close(p0); @@ -165,7 +155,7 @@ filsysinit(Channel *cxfidalloc) /* * Post srv pipe */ - snprint(srvpipe, sizeof(srvpipe), "/srv/rio.%s.%d", fs->user, pid); + snprint(srvpipe, sizeof(srvpipe), "/srv/rio.%s.%lud", fs->user, (ulong)getpid()); post(srvpipe, "wsys", fs->cfd); return fs; @@ -234,7 +224,7 @@ filsysmount(Filsys *fs, int id) char buf[32]; close(fs->sfd); /* close server end so mount won't hang if exiting */ - sprint(buf, "%d", id); + snprint(buf, sizeof buf, "%d", id); if(mount(fs->cfd, -1, "/mnt/wsys", MREPL, buf) == -1){ fprint(2, "mount failed: %r\n"); return -1; diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index a42721fac..a28fb2ccc 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -244,7 +244,7 @@ putsnarf(void) if(snarffd<0 || nsnarf==0) return; - fd = open("/dev/snarf", OWRITE); + fd = open("/dev/snarf", OWRITE|OCEXEC); if(fd < 0) return; /* snarf buffer could be huge, so fprint will truncate; do it in blocks */ @@ -394,12 +394,13 @@ portion(int x, int lo, int hi) { x -= lo; hi -= lo; - if(hi < 20) - return x > 0 ? 2 : 0; - if(x < 20) - return 0; - if(x > hi-20) - return 2; + if(x < hi/2){ + if(x < 20) + return 0; + } else { + if(x > hi-20) + return 2; + } return 1; } @@ -857,7 +858,7 @@ sweep(void) } void -drawedge(Image **bp, Rectangle r) +drawedge(Image **bp, Image *col, Rectangle r) { Image *b = *bp; if(b != nil && Dx(b->r) == Dx(r) && Dy(b->r) == Dy(r)) @@ -865,28 +866,30 @@ drawedge(Image **bp, Rectangle r) else{ freeimage(b); b = allocwindow(wscreen, r, Refbackup, DNofill); - if(b != nil) draw(b, r, sizecol, nil, ZP); + if(b != nil) draw(b, r, col, nil, ZP); *bp = b; } } void -drawborder(Rectangle r, int show) +drawborder(Rectangle r, Image *col) { - static Image *b[4]; - int i; - if(show == 0){ - for(i = 0; i < 4; i++){ - freeimage(b[i]); - b[i] = nil; - } - }else{ + static Image *b[4], *lastcol; + + if(col != lastcol){ + freeimage(b[0]), b[0] = nil; + freeimage(b[1]), b[1] = nil; + freeimage(b[2]), b[2] = nil; + freeimage(b[3]), b[3] = nil; + } + if(col != nil){ r = canonrect(r); - drawedge(&b[0], Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y)); - drawedge(&b[1], Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth)); - drawedge(&b[2], Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y)); - drawedge(&b[3], Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y)); + drawedge(&b[0], col, Rect(r.min.x, r.min.y, r.min.x+Borderwidth, r.max.y)); + drawedge(&b[1], col, Rect(r.min.x+Borderwidth, r.min.y, r.max.x-Borderwidth, r.min.y+Borderwidth)); + drawedge(&b[2], col, Rect(r.max.x-Borderwidth, r.min.y, r.max.x, r.max.y)); + drawedge(&b[3], col, Rect(r.min.x+Borderwidth, r.max.y-Borderwidth, r.max.x-Borderwidth, r.max.y)); } + lastcol = col; } Image* @@ -901,17 +904,17 @@ drag(Window *w) dm = subpt(om, w->screenr.min); d = subpt(w->screenr.max, w->screenr.min); op = subpt(om, dm); - drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1); + drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), sizecol); while(mouse->buttons==4){ p = subpt(mouse->xy, dm); if(!eqpt(p, op)){ - drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1); + drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), sizecol); op = p; } readmouse(mousectl); } r = Rect(op.x, op.y, op.x+d.x, op.y+d.y); - drawborder(r, 0); + drawborder(r, nil); p = mouse->xy; riosetcursor(inborder(r, p) ? corners[whichcorner(r, p)] : nil); menuing = FALSE; @@ -935,7 +938,7 @@ bandsize(Window *w) or = w->screenr; but = mouse->buttons; startp = onscreen(mouse->xy); - drawborder(or, 1); + drawborder(or, sizecol); while(mouse->buttons == but) { p = onscreen(mouse->xy); which = whichcorner(or, p); @@ -945,12 +948,14 @@ bandsize(Window *w) } r = whichrect(or, p, owhich); if(!eqrect(r, or) && goodrect(r)){ + drawborder(r, sizecol); or = r; - drawborder(r, 1); } readmouse(mousectl); } - drawborder(or, 0); + drawborder(or, nil); + if(!goodrect(or)) + riosetcursor(nil); if(mouse->buttons!=0 || !goodrect(or) || eqrect(or, w->screenr) || abs(p.x-startp.x)+abs(p.y-startp.y) <= 1){ flushimage(display, 1); diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c index 59c9246c9..bef98fda9 100644 --- a/sys/src/cmd/rio/wctl.c +++ b/sys/src/cmd/rio/wctl.c @@ -88,14 +88,19 @@ static char *params[] = { int goodrect(Rectangle r) { - if(!eqrect(canonrect(r), r)) + if(badrect(r) || !eqrect(canonrect(r), r)) return 0; /* reasonable sizes only please */ if(Dx(r) > BIG*Dx(screen->r)) return 0; if(Dy(r) > BIG*Dy(screen->r)) return 0; - if(Dx(r) < 100 || Dy(r) < 3*font->height) + /* + * the height has to be big enough to fit one line of text. + * that includes the border on each side with an extra pixel + * so that the text is still drawn + */ + if(Dx(r) < 100 || Dy(r) < 2*(Borderwidth+1)+font->height) return 0; /* window must be on screen */ if(!rectXrect(screen->r, r)) diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c index 9734fd18f..1fd1b671c 100644 --- a/sys/src/cmd/rio/wind.c +++ b/sys/src/cmd/rio/wind.c @@ -1420,7 +1420,7 @@ wclosewin(Window *w) void wsetpid(Window *w, int pid, int dolabel) { - char buf[64]; + char buf[32]; int ofd; ofd = w->notefd; @@ -1428,11 +1428,11 @@ wsetpid(Window *w, int pid, int dolabel) w->notefd = -1; else { if(dolabel){ - snprint(buf, sizeof(buf), "rc %d", pid); + snprint(buf, sizeof(buf), "rc %lud", (ulong)pid); free(w->label); w->label = estrdup(buf); } - snprint(buf, sizeof(buf), "/proc/%d/notepg", pid); + snprint(buf, sizeof(buf), "/proc/%lud/notepg", (ulong)pid); w->notefd = open(buf, OWRITE|OCEXEC); } if(ofd >= 0) diff --git a/sys/src/cmd/srvfs.c b/sys/src/cmd/srvfs.c index d5c028150..a500c8ed2 100644 --- a/sys/src/cmd/srvfs.c +++ b/sys/src/cmd/srvfs.c @@ -12,7 +12,7 @@ void main(int argc, char **argv) { char *ename, *arglist[16], **argp; - int n, fd, pipefd[2]; + int fd, pipefd[2]; char buf[64]; int perm = 0600; @@ -39,14 +39,27 @@ main(int argc, char **argv) *argp++ = "-R"; break; }ARGEND - *argp = 0; if(argc != 2) usage(); + *argp++ = "-r"; + *argp++ = argv[1]; + *argp = 0; if(pipe(pipefd) < 0){ fprint(2, "can't pipe: %r\n"); exits("pipe"); } + if(argv[0][0] == '/') + strecpy(buf, buf+sizeof buf, argv[0]); + else + snprint(buf, sizeof buf, "/srv/%s", argv[0]); + fd = create(buf, OWRITE|ORCLOSE, perm); + if(fd < 0){ + fprint(2, "can't create %s: %r\n", buf); + exits("create"); + } + fprint(fd, "%d", pipefd[1]); + close(pipefd[1]); switch(rfork(RFPROC|RFNOWAIT|RFNOTEG|RFFDG)){ case -1: @@ -56,39 +69,11 @@ main(int argc, char **argv) dup(pipefd[0], 0); dup(pipefd[0], 1); close(pipefd[0]); - close(pipefd[1]); exec(ename, arglist); fprint(2, "can't exec exportfs: %r\n"); exits("exec"); default: break; } - close(pipefd[0]); - if(fprint(pipefd[1], "%s", argv[1]) < 0){ - fprint(2, "can't write pipe: %r\n"); - exits("write"); - } - n = read(pipefd[1], buf, sizeof buf-1); - if(n < 0){ - fprint(2, "can't read pipe: %r\n"); - exits("read"); - } - buf[n] = 0; - if(n != 2 || strcmp(buf, "OK") != 0){ - fprint(2, "not OK (%d): %s\n", n, buf); - exits("OK"); - } - if(argv[0][0] == '/') - strecpy(buf, buf+sizeof buf, argv[0]); - else - snprint(buf, sizeof buf, "/srv/%s", argv[0]); - fd = create(buf, OWRITE, perm); - if(fd < 0){ - fprint(2, "can't create %s: %r\n", buf); - exits("create"); - } - fprint(fd, "%d", pipefd[1]); - close(fd); - close(pipefd[1]); exits(0); } diff --git a/sys/src/cmd/vmx/dat.h b/sys/src/cmd/vmx/dat.h index 25a1898a0..b6e375a8e 100644 --- a/sys/src/cmd/vmx/dat.h +++ b/sys/src/cmd/vmx/dat.h @@ -11,6 +11,7 @@ enum { VMDEAD, }; extern int state; +extern int debug; enum { BY2PG = 4096 diff --git a/sys/src/cmd/vmx/exith.c b/sys/src/cmd/vmx/exith.c index 48f054c01..185c22e07 100644 --- a/sys/src/cmd/vmx/exith.c +++ b/sys/src/cmd/vmx/exith.c @@ -1,9 +1,8 @@ #include <u.h> #include <libc.h> -#include <thread.h> -#include <bio.h> #include "dat.h" #include "fns.h" +#include "x86.h" int persist = 1; @@ -118,109 +117,167 @@ eptfault(ExitInfo *ei) typedef struct CPUID CPUID; struct CPUID { - u32int idx; u32int ax, bx, cx, dx; }; -static CPUID *cpuidf; -static int ncpuidf; +static u32int cpuidmax; +static u32int cpuidmaxext; +static CPUID leaf1; +static struct { + uvlong miscen; +}msr; -static void -auxcpuidproc(void *vpfd) -{ - int *pfd; - - pfd = vpfd; - close(pfd[1]); - close(0); - open("/dev/null", OREAD); - dup(pfd[0], 1); - close(pfd[0]); - procexecl(nil, "/bin/aux/cpuid", "cpuid", "-r", nil); - threadexits("exec: %r"); -} +static uchar _cpuid[] = { + 0x5E, /* POP SI (PC) */ + 0x5D, /* POP BP (CPUID&) */ + 0x58, /* POP AX */ + 0x59, /* POP CX */ + + 0x51, /* PUSH CX */ + 0x50, /* PUSH AX */ + 0x55, /* PUSH BP */ + 0x56, /* PUSH SI */ + + 0x31, 0xDB, /* XOR BX, BX */ + 0x31, 0xD2, /* XOR DX, DX */ + + 0x0F, 0xA2, /* CPUID */ + + 0x89, 0x45, 0x00, /* MOV AX, 0(BP) */ + 0x89, 0x5d, 0x04, /* MOV BX, 4(BP) */ + 0x89, 0x4d, 0x08, /* MOV CX, 8(BP) */ + 0x89, 0x55, 0x0C, /* MOV DX, 12(BP) */ + 0xC3, /* RET */ +}; + +static CPUID (*getcpuid)(ulong ax, ulong cx) = (CPUID(*)(ulong, ulong)) _cpuid; void cpuidinit(void) { - int pfd[2]; - Biobuf *bp; - char *l, *f[5]; - CPUID *cp; - - pipe(pfd); - procrfork(auxcpuidproc, pfd, 4096, RFFDG); - close(pfd[0]); - bp = Bfdopen(pfd[1], OREAD); - if(bp == nil) sysfatal("Bopenfd: %r"); - for(; l = Brdstr(bp, '\n', 1), l != nil; free(l)){ - if(tokenize(l, f, 5) < 5) continue; - cpuidf = realloc(cpuidf, (ncpuidf + 1) * sizeof(CPUID)); - cp = cpuidf + ncpuidf++; - cp->idx = strtoul(f[0], nil, 16); - cp->ax = strtoul(f[1], nil, 16); - cp->bx = strtoul(f[2], nil, 16); - cp->cx = strtoul(f[3], nil, 16); - cp->dx = strtoul(f[4], nil, 16); - } - Bterm(bp); - close(pfd[1]); -} + CPUID r; + int f; -CPUID * -getcpuid(ulong idx) -{ - CPUID *cp; - - for(cp = cpuidf; cp < cpuidf + ncpuidf; cp++) - if(cp->idx == idx) - return cp; - return nil; + if(sizeof(uintptr) == 8) /* patch out POP BP -> POP AX */ + _cpuid[1] = 0x58; + segflush(_cpuid, sizeof(_cpuid)); + + r = getcpuid(0, 0); + cpuidmax = r.ax; + r = getcpuid(0x80000000, 0); + cpuidmaxext = r.ax; + leaf1 = getcpuid(1, 0); + + memset(&msr, 0, sizeof(msr)); + if((f = open("/dev/msr", OREAD)) >= 0){ + pread(f, &msr.miscen, 8, 0x1a0); + msr.miscen &= 1<<0; /* fast strings */ + close(f); + } } -int maxcpuid = 7; +static int xsavesz[] = { + [1] = 512+64, + [3] = 512+64, + [7] = 512+64+256, +}; static void cpuid(ExitInfo *ei) { u32int ax, bx, cx, dx; - CPUID *cp; - static CPUID def; - + CPUID cp; + ax = rget(RAX); - cp = getcpuid(ax); - if(cp == nil) cp = &def; + cx = rget(RCX); + bx = dx = 0; + cp = getcpuid(ax, cx); switch(ax){ - case 0: /* highest register & GenuineIntel */ - ax = maxcpuid; - bx = cp->bx; - dx = cp->dx; - cx = cp->cx; + case 0x00: /* highest register & GenuineIntel */ + ax = MIN(cpuidmax, 0x18); + bx = cp.bx; + dx = cp.dx; + cx = cp.cx; break; - case 1: /* features */ - ax = cp->ax; - bx = cp->bx & 0xffff; - cx = cp->cx & 0x60de2203; - dx = cp->dx & 0x0782a179; + case 0x01: /* features */ + ax = cp.ax; + bx = cp.bx & 0xffff; + /* some features removed, hypervisor added */ + cx = cp.cx & 0x76de3217 | 0x80000000UL; + dx = cp.dx & 0x0f8aa579; + if(leaf1.cx & 1<<27){ + if(rget("cr4real") & Cr4Osxsave) + cx |= 1<<27; + }else{ + cx &= ~0x1c000000; + } break; - case 2: goto literal; /* cache stuff */ - case 3: goto zero; /* processor serial number */ - case 4: goto zero; /* cache stuff */ - case 5: goto zero; /* monitor/mwait */ - case 6: goto zero; /* thermal management */ - case 7: goto zero; /* more features */ - case 10: goto zero; /* performance counters */ + case 0x02: goto literal; /* cache stuff */ + case 0x03: goto zero; /* processor serial number */ + case 0x04: goto literal; /* cache stuff */ + case 0x05: goto zero; /* monitor/mwait */ + case 0x06: goto zero; /* thermal management */ + case 0x07: /* more features */ + if(cx == 0){ + ax = 0; + bx = cp.bx & 0x2369; + cx = 0; + if((leaf1.cx & 1<<27) == 0) + bx &= ~0xdc230020; + }else{ + goto zero; + } + break; + case 0x08: goto zero; + case 0x09: goto literal; /* direct cache access */ + case 0x0a: goto zero; /* performance counters */ + case 0x0b: goto zero; /* extended topology */ + case 0x0c: goto zero; + case 0x0d: /* extended state */ + if((leaf1.cx & 1<<27) == 0) + goto zero; + if(cx == 0){ /* main leaf */ + ax = cp.ax & 7; /* x87, sse, avx */ + bx = xsavesz[rget("xcr0")]; /* current xsave size */ + cx = xsavesz[ax]; /* max xsave size */ + }else if(cx == 1){ /* sub leaf */ + ax = cp.ax & 7; /* xsaveopt, xsavec, xgetbv1 */ + bx = xsavesz[rget("xcr0")]; + cx = 0; + }else if(cx == 2){ + ax = xsavesz[7] - xsavesz[3]; + bx = xsavesz[3]; + cx = 0; + }else{ + goto zero; + } + break; + case 0x0f: goto zero; /* RDT */ + case 0x10: goto zero; /* RDT */ + case 0x12: goto zero; /* SGX */ + case 0x14: goto zero; /* PT */ + case 0x15: goto zero; /* TSC */ + case 0x16: goto zero; /* cpu clock */ + case 0x17: goto zero; /* SoC */ + case 0x18: goto literal; /* pages, tlb */ + + case 0x40000000: /* hypervisor */ + ax = 0; + bx = 0x4b4d564b; /* act as KVM */ + cx = 0x564b4d56; + dx = 0x4d; + break; + case 0x80000000: /* highest register */ - ax = 0x80000008; - bx = cx = dx = 0; + ax = MIN(cpuidmaxext, 0x80000008); + cx = 0; break; case 0x80000001: /* signature & ext features */ - ax = cp->ax; - bx = 0; - cx = cp->cx & 0x121; + ax = cp.ax; + cx = cp.cx & 0x121; if(sizeof(uintptr) == 8) - dx = cp->dx & 0x24100800; + dx = cp.dx & 0x24100800; else - dx = cp->dx & 0x04100000; + dx = cp.dx & 0x04100000; break; case 0x80000002: goto literal; /* brand string */ case 0x80000003: goto literal; /* brand string */ @@ -230,18 +287,16 @@ cpuid(ExitInfo *ei) case 0x80000007: goto zero; /* invariant tsc */ case 0x80000008: goto literal; /* address bits */ literal: - ax = cp->ax; - bx = cp->bx; - cx = cp->cx; - dx = cp->dx; + ax = cp.ax; + bx = cp.bx; + cx = cp.cx; + dx = cp.dx; break; default: - vmerror("unknown cpuid field eax=%#ux", ax); + if((ax & 0xf0000000) != 0x40000000) + vmdebug("unknown cpuid field eax=%#ux", ax); zero: - ax = 0; - bx = 0; - cx = 0; - dx = 0; + ax = cx = 0; break; } rset(RAX, ax); @@ -267,12 +322,15 @@ rdwrmsr(ExitInfo *ei) else rset("pat", val); break; case 0x8B: val = 0; break; /* microcode update */ + case 0x1A0: /* IA32_MISC_ENABLE */ + if(rd) val = msr.miscen; + break; default: if(rd){ - vmerror("read from unknown MSR %#ux ignored", cx); + vmdebug("read from unknown MSR %#ux ignored", cx); val = 0; }else - vmerror("write to unknown MSR %#ux ignored (val=%#ullx)", cx, val); + vmdebug("write to unknown MSR %#ux ignored (val=%#ullx)", cx, val); break; } if(rd){ @@ -310,7 +368,7 @@ movcr(ExitInfo *ei) case 0: switch(q >> 4 & 3){ case 0: - vmdebug("illegal CR0 write, value %#ux", rget(x86reg[q >> 8 & 15])); + vmdebug("illegal CR0 write, value %#ux", (u32int)rget(x86reg[q >> 8 & 15])); rset("cr0real", rget(x86reg[q >> 8 & 15])); skipinstr(ei); break; @@ -332,7 +390,7 @@ movcr(ExitInfo *ei) case 4: switch(q >> 4 & 3){ case 0: - vmdebug("illegal CR4 write, value %#ux", rget(x86reg[q >> 8 & 15])); + vmdebug("illegal CR4 write, value %#ux", (u32int)rget(x86reg[q >> 8 & 15])); rset("cr4real", rget(x86reg[q >> 8 & 15])); skipinstr(ei); break; @@ -347,7 +405,7 @@ movcr(ExitInfo *ei) } break; default: - vmerror("access to unknown control register CR%d", ei->qual & 15); + vmerror("access to unknown control register CR%ud", q & 15); postexc("#ud", NOERRC); } } @@ -373,6 +431,26 @@ irqackhand(ExitInfo *ei) irqack(ei->qual); } +static void +xsetbv(ExitInfo *ei) +{ + uvlong v; + + /* this should also #ud if LOCK prefix is used */ + + v = rget(RAX)&0xffffffff | rget(RDX)<<32; + if(rget(RCX) & 0xffffffff) + postexc("#gp", 0); + else if(v != 1 && v != 3 && v != 7) + postexc("#gp", 0); + else if((leaf1.cx & 1<<26) == 0 || (rget("cr4real") & Cr4Osxsave) == 0) + postexc("#ud", NOERRC); + else{ + rset("xcr0", v); + skipinstr(ei); + } +} + typedef struct ExitType ExitType; struct ExitType { char *name; @@ -389,6 +467,7 @@ static ExitType etypes[] = { {".movdr", movdr}, {"#db", dbgexc}, {"movcr", movcr}, + {".xsetbv", xsetbv}, }; void diff --git a/sys/src/cmd/vmx/fns.h b/sys/src/cmd/vmx/fns.h index d73e5fe1d..06643a9aa 100644 --- a/sys/src/cmd/vmx/fns.h +++ b/sys/src/cmd/vmx/fns.h @@ -1,3 +1,4 @@ +#define MIN(a,b) ((a)<(b)?(a):(b)) void *emalloc(ulong); void loadkernel(char *); uvlong rget(char *); @@ -10,7 +11,8 @@ void pitadvance(void); void rtcadvance(void); void settimer(vlong targ); void vmerror(char *, ...); -#define vmdebug vmerror +#pragma varargck argpos vmerror 1 +#define vmdebug if(!debug) {} else vmerror int ctl(char *, ...); void registermmio(uvlong, uvlong, uvlong (*)(int, uvlong, uvlong)); void irqline(int, int); diff --git a/sys/src/cmd/vmx/ide.c b/sys/src/cmd/vmx/ide.c index 162cac1c0..1e7cd1a7e 100644 --- a/sys/src/cmd/vmx/ide.c +++ b/sys/src/cmd/vmx/ide.c @@ -118,7 +118,7 @@ idegoio(IDE *d, int wr) addr = getlba(d); if(addr < 0){ - vmerror("ide%d: access to invalid sector address (access to CHS=(%#.4ux,%#ux,%#.2ux); geometry is (%#.4ux,%#ux,%#.2ux)", d-ide, d->cyl, d->head&0xf, d->sec, d->lcyl, d->lhead, d->lsec); + vmerror("ide%zd: access to invalid sector address (access to CHS=(%#.4ux,%#ux,%#.2ux); geometry is (%#.4ux,%#ux,%#.2ux)", d-ide, d->cyl, d->head&0xf, d->sec, d->lcyl, d->lhead, d->lsec); postexc("#bp", NOERRC); d->stat = IDEDRDY | IDEDSC | IDEDRQ | IDEERR; d->err = IDEIDNF; @@ -325,7 +325,7 @@ ideioproc(void *dp) qunlock(io); werrstr("eof"); if(getsector(a+i, p) < 0 && pread(d->fd, p, 512, (a+i)*512) < 512){ - vmerror("ide%d: read: %r", d - ide); + vmerror("ide%zd: read: %r", d - ide); qlock(io); io->err = IDEUNC; qunlock(io); @@ -355,7 +355,7 @@ idecmd(IDE *d, u8int cmd) break; default: if((d->flags & IDEPRESENT) == 0){ - vmerror("ide%d: command %#ux issued to absent drive", d-ide, cmd); + vmerror("ide%zd: command %#ux issued to absent drive", d-ide, cmd); return; } } @@ -435,7 +435,7 @@ idecmd(IDE *d, u8int cmd) case 0x66: d->flags |= IDEKEEPFEAT; break; /* retain settings */ case 0xcc: d->flags &= ~IDEKEEPFEAT; break; /* revert to default on reset */ default: - vmerror("ide%d: unknown feature %#ux", d-ide, d->feat); + vmerror("ide%zd: unknown feature %#ux", d-ide, d->feat); d->stat = IDEDRDY|IDEDSC|IDEERR; d->err = IDEABRT; return; @@ -443,7 +443,7 @@ idecmd(IDE *d, u8int cmd) d->stat = IDEDRDY|IDEDSC; break; default: - vmerror("ide%d: unknown command %#ux", d-ide, cmd); + vmerror("ide%zd: unknown command %#ux", d-ide, cmd); d->stat = IDEDRDY|IDEDSC|IDEERR; d->err = IDEABRT; } diff --git a/sys/src/cmd/vmx/io.c b/sys/src/cmd/vmx/io.c index 2de8fe605..25244b4e0 100644 --- a/sys/src/cmd/vmx/io.c +++ b/sys/src/cmd/vmx/io.c @@ -292,7 +292,7 @@ picio(int isin, u16int port, u32int val, int sz, void *) p->imr = 0; p->prio = 7; p->flags = 0; - if((val & 0x0b) != 0x01) vmerror("PIC%ld ICW1 with unsupported value %#ux", p-pic, val); + if((val & 0x0b) != 0x01) vmerror("PIC%zd ICW1 with unsupported value %#ux", p-pic, (u32int)val); p->init = 1; return 0; } @@ -347,7 +347,7 @@ picio(int isin, u16int port, u32int val, int sz, void *) case 0xa1: switch(p->init){ default: - vmerror("write to PIC%ld in init=%d state", p-pic, p->init); + vmerror("write to PIC%zd in init=%d state", p-pic, p->init); return 0; case 1: p->base = val; @@ -355,11 +355,11 @@ picio(int isin, u16int port, u32int val, int sz, void *) return 0; case 2: if(p == &pic[0] && val != 4 || p == &pic[1] && val != 2) - vmerror("PIC%ld ICW3 with unsupported value %#ux", p-pic, val); + vmerror("PIC%zd ICW3 with unsupported value %#ux", p-pic, val); p->init = 3; return 0; case 3: - if((val & 0xfd) != 1) vmerror("PIC%ld ICW4 with unsupported value %#ux", p-pic, val); + if((val & 0xfd) != 1) vmerror("PIC%zd ICW4 with unsupported value %#ux", p-pic, val); if((val & 2) != 0) p->flags |= AEOI; p->init = 4; picupdate(p); @@ -726,7 +726,7 @@ kbdcmd(u8int val) case 0xf2: keyputc(0xfa); keyputc(0xab); keyputc(0x41); break; /* keyboard id */ case 0xee: keyputc(0xee); break; /* echo */ default: - vmerror("unknown kbd command %#ux", val); + vmdebug("unknown kbd command %#ux", val); keyputc(0xfe); } } @@ -1203,9 +1203,9 @@ u32int iowhine(int isin, u16int port, u32int val, int sz, void *mod) { if(isin) - vmerror("%s%sread from unknown i/o port %#ux ignored (sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, sz, rget(RPC)); + vmdebug("%s%sread from unknown i/o port %#ux ignored (sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, sz, rget(RPC)); else - vmerror("%s%swrite to unknown i/o port %#ux ignored (val=%#ux, sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, val, sz, rget(RPC)); + vmdebug("%s%swrite to unknown i/o port %#ux ignored (val=%#ux, sz=%d, pc=%#ullx)", mod != nil ? mod : "", mod != nil ? ": " : "", port, val, sz, rget(RPC)); return -1; } diff --git a/sys/src/cmd/vmx/mkfile b/sys/src/cmd/vmx/mkfile index e52b53466..78842c3dc 100644 --- a/sys/src/cmd/vmx/mkfile +++ b/sys/src/cmd/vmx/mkfile @@ -2,6 +2,7 @@ BIN=/$objtype/bin TARG=vmx +CLEANFILES=$O.vmxgdb HFILES=dat.h fns.h OFILES=\ vmx.$O \ @@ -19,6 +20,10 @@ OFILES=\ </sys/src/cmd/mkone +default:V: all + +all:V: $O.out $O.vmxgdb + install:V: $BIN/vmxgdb $BIN/vmxgdb: $O.vmxgdb diff --git a/sys/src/cmd/vmx/nanosec.c b/sys/src/cmd/vmx/nanosec.c index ac418483d..1301e9faf 100644 --- a/sys/src/cmd/vmx/nanosec.c +++ b/sys/src/cmd/vmx/nanosec.c @@ -17,14 +17,15 @@ nanosec(void) return nsec() - xstart; if(fasthz == 0){ - if((fasthz = _tos->cyclefreq) == 0){ - fasthz = ~0ULL; + if(_tos->cyclefreq){ + cycles(&xstart); + fasthz = _tos->cyclefreq; + } else { xstart = nsec(); + fasthz = ~0ULL; fprint(2, "cyclefreq not available, falling back to nsec()\n"); fprint(2, "you might want to disable aux/timesync\n"); return 0; - }else{ - cycles(&xstart); } } cycles(&x); diff --git a/sys/src/cmd/vmx/vesa.c b/sys/src/cmd/vmx/vesa.c index 35c7a0d38..61eeb5c2c 100644 --- a/sys/src/cmd/vmx/vesa.c +++ b/sys/src/cmd/vmx/vesa.c @@ -622,7 +622,8 @@ vesathread(void *) if(vesaddc(&ur) < 0 || vesasetregs(sp, &ur) < 0) continue; break; default: - vmerror("vesa: unsupported function %#x", ur.ax); + vesasetax(sp, 0x0100); + vmdebug("vesa: unsupported function %#x", ur.ax); } } } diff --git a/sys/src/cmd/vmx/vga.c b/sys/src/cmd/vmx/vga.c index 9fadff15e..b59eb44a1 100644 --- a/sys/src/cmd/vmx/vga.c +++ b/sys/src/cmd/vmx/vga.c @@ -178,7 +178,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) switch(vga.sidx){ case 0: vga.seq[vga.sidx] = val & 3; return 0; case 4: vga.seq[vga.sidx] = val & 0xe; return 0; - default: vmerror("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; + default: vmdebug("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; } case 0x3c6: return 0; case 0x3c7: vga.rdidx = val << 2; return 0; @@ -194,7 +194,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 4: vga.graph[vga.gidx] = val & 3; break; case 8: vga.graph[vga.gidx] = val; break; default: - vmerror("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val); + vmdebug("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val); } return 0; case 0x3d4: vga.cidx = val; return 0; @@ -204,7 +204,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) vga.crtc[vga.cidx] = val; return 0; default: - vmerror("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val); + vmdebug("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val); } return 0; case 0x103c0: return vga.aidx & 0x3f; @@ -215,7 +215,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 0: case 4: return vga.seq[vga.sidx]; - default: vmerror("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; + default: vmdebug("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0; } case 0x103c6: return 0xff; case 0x103c7: return vga.rdidx >> 2; @@ -232,7 +232,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 8: return vga.graph[vga.gidx]; default: - vmerror("vga: read from unknown graphics register %#ux", vga.gidx); + vmdebug("vga: read from unknown graphics register %#ux", vga.gidx); return 0; } case 0x103d4: return vga.cidx; @@ -241,7 +241,7 @@ vgaio(int isin, u16int port, u32int val, int sz, void *) case 10: case 11: case 12: case 13: case 14: case 15: return vga.crtc[vga.cidx]; default: - vmerror("vga: read from unknown CRTC register %#ux", vga.cidx); + vmdebug("vga: read from unknown CRTC register %#ux", vga.cidx); return 0; } case 0x103ca: @@ -374,7 +374,7 @@ keyproc(void *) nkdown[k->code >> 6] |= 1ULL<<(k->code&63); break; } - if(k == nil) vmerror("unknown key %d", r); + if(k == nil) vmdebug("unknown key %d", r); } if(mousegrab && (nkdown[0]>>29 & 1) != 0 && (nkdown[0]>>56 & 1) != 0){ mousegrab = 0; @@ -737,7 +737,7 @@ vgafbparse(char *fbstring) void -vgainit(void) +vgainit(int new) { char buf[512]; int i; @@ -760,7 +760,7 @@ vgainit(void) sysfatal("got nil ptr for framebuffer"); } snprint(buf, sizeof(buf), "-dx %d -dy %d", maxw+50, maxh+50); - if(newwindow(buf) < 0 || initdraw(nil, nil, "vmx") < 0) + if((new && newwindow(buf) < 0) || initdraw(nil, nil, "vmx") < 0) sysfatal("failed to initialize graphics: %r"); screeninit(1); flushimage(display, 1); diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c index 1a974a042..b3b73d845 100644 --- a/sys/src/cmd/vmx/vmx.c +++ b/sys/src/cmd/vmx/vmx.c @@ -11,7 +11,7 @@ Region *mmap; int ctlfd, regsfd, mapfd, waitfd; Channel *waitch, *sleepch, *notifch; enum { MSEC = 1000*1000, MinSleep = MSEC, SleeperPoll = 2000*MSEC } ; -int getexit, state; +int getexit, state, debug; typedef struct VmxNotif VmxNotif; struct VmxNotif { void (*f)(void *); @@ -320,9 +320,6 @@ gend(void *v) return (u8int *) v + gavail(v); } -void *tmp, *vgamem; -uvlong tmpoff, vgamemoff; - static void mksegment(char *sn) { @@ -355,8 +352,9 @@ mksegment(char *sn) close(fd); gmem = segattach(0, sn, nil, sz); if(gmem == (void*)-1) sysfatal("segattach: %r"); + }else{ + memset(gmem, 0, sz > 1<<24 ? 1<<24 : sz); } - memset(gmem, 0, sz > 1<<24 ? 1<<24 : sz); p = gmem; for(r = mmap; r != nil; r = r->next){ if(r->segname == nil) continue; @@ -365,14 +363,12 @@ mksegment(char *sn) p += r->end - r->start; r->ve = p; } - vgamem = p; - vgamemoff = p - gmem; - regptr(0xa0000)->segoff = vgamemoff; - regptr(0xa0000)->v = vgamem; + /* vga */ + r = regptr(0xa0000); + r->segoff = p - gmem; + r->v = p; p += 256*1024; - regptr(0xa0000)->ve = p; - tmp = p; - tmpoff = p - gmem; + r->ve = p; for(r = mmap; r != nil; r = r->next) modregion(r); @@ -504,7 +500,7 @@ sendnotif(void (*f)(void *), void *arg) send(notifch, ¬if); } -extern void vgainit(void); +extern void vgainit(int); extern void pciinit(void); extern void pcibusmap(void); extern void cpuidinit(void); @@ -574,7 +570,7 @@ usage(void) for(p = blanks; *p != 0; p++) *p = ' '; fprint(2, "usage: %s [ -M mem ] [ -c com1rd[,com1wr] ] [ -C com2rd[,com2r] ] [ -n nic ]\n", argv0); - fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v vga ] [ -9 srv ] kernel [ args ... ]\n", blanks); + fprint(2, " %s [ -d blockfile ] [ -m module ] [ -v|-w vga ] [ -9 srv ] kernel [ args ... ]\n", blanks); threadexitsall("usage"); } @@ -590,6 +586,7 @@ threadmain(int argc, char **argv) static uvlong gmemsz = 64*1024*1024; static char *srvname; extern uintptr fbsz, fbaddr; + int newwin = 0; int i; quotefmtinstall(); @@ -598,7 +595,7 @@ threadmain(int argc, char **argv) waitch = chancreate(sizeof(char *), 32); sleepch = chancreate(sizeof(ulong), 32); notifch = chancreate(sizeof(VmxNotif), 16); - + ARGBEGIN { case 'm': bootmod = realloc(bootmod, (bootmodn + 1) * sizeof(char *)); @@ -633,10 +630,15 @@ threadmain(int argc, char **argv) } edevn++; break; + case 'D': + debug++; + break; case 'M': gmemsz = siparse(EARGF(usage())); if(gmemsz != (uintptr) gmemsz) sysfatal("too much memory for address space"); break; + case 'w': + newwin = 1; case 'v': vgafbparse(EARGF(usage())); break; @@ -673,7 +675,7 @@ threadmain(int argc, char **argv) loadkernel(argv[0]); pciinit(); - vgainit(); + vgainit(newwin); for(i = 0; i < edevn; i++) if(edev[i](edevaux[i]) < 0) sysfatal("%s: %r", edevt[i]); diff --git a/sys/src/cmd/vmx/x86.h b/sys/src/cmd/vmx/x86.h index da2b16847..4fe7947e1 100644 --- a/sys/src/cmd/vmx/x86.h +++ b/sys/src/cmd/vmx/x86.h @@ -22,8 +22,9 @@ enum { enum { Cr0Pg = 1<<31, - Cr4Pse = 1<<4, - Cr4Pae = 1<<5, + Cr4Pse = 1<<4, + Cr4Pae = 1<<5, + Cr4Osxsave = 1<<18, EferLme = 1<<8, }; |