~kris/9p

9hist

895278034d4570dac2e4070d588f6e08059fa5db — David du Colombier 34 years ago 93e67d8
Plan 9 from Bell Labs 1992-03-19
M boot/boot.c => boot/boot.c +0 -1
@@ 111,7 111,6 @@ main(int argc, char *argv[])
	settime(islocal);
	swapproc();

	sleep(1000);
	sprint(cmd, "/%s/init", cputype);
	sprint(flags, "-%s%s", cpuflag ? "c" : "t", mflag ? "m" : "");
	execl(cmd, "init", flags, 0);

M boot/nopsession.c => boot/nopsession.c +39 -37
@@ 4,53 4,55 @@
#include "../boot/boot.h"

static Fcall	hdr;
static char	buf[4*1024];

void
nop(int fd)
static void
rpc(int fd, int type)
{
	long n;
	int n, l;
	char buf[128], *p;

	print("nop...");
	hdr.type = Tnop;
	hdr.type = type;
	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");
		fatal("write rpc");

	print("...");
	p = buf;
	l = 0;
	while(l < 3) {
		n = read(fd, p, 3);
		if(n <= 0)
			fatal("read rpc");
		if(n == 2 && l == 0 && buf[0] == 'O' && buf[1] == 'K')
			continue;
		p += n;
		l += n;
	}
	if(convM2S(buf, &hdr, n) == 0){
		print("%ux %ux %ux\n", buf[0], buf[1], buf[2]);
		fatal("rpc format");
	}
	if(hdr.tag != NOTAG)
		fatal("rpc tag not NOTAG");
	if(hdr.type == Rerror){
		print("error %s;", hdr.ename);
		fatal("remote error");
	}
	if(hdr.type != Rnop)
		fatal("not Rnop");
	if(hdr.type != type+1)
		fatal("not reply");
}

void
session(int fd)
nop(int fd)
{
	long n;
	print("nop");
	rpc(fd, Tnop);
}

	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");
void
session(int fd)
{
	print("session");
	rpc(fd, Tsession);
}

M gnot/lib.h => gnot/lib.h +3 -3
@@ 62,9 62,9 @@ extern	int	print(char*, ...);
 */
extern	long	strtol(char*, char**, int);
extern	ulong	strtoul(char*, char**, int);
extern	long	etext;
extern	long	edata;
extern	long	end;
extern	char	etext[];
extern	char	edata[];
extern	char	end[];
/*
 * Syscall data structures
 */

M port/devarp.c => port/devarp.c +2 -0
@@ 286,6 286,8 @@ arpwrite(Chan *c, char *a, long n, ulong offset)
void
arpopn(Queue *q, Stream *s)
{
	if(Myip[Myself])
		error(Einuse);
	USED(q, s);
}


M port/devcons.c => port/devcons.c +3 -0
@@ 240,6 240,9 @@ echo(Rune r, char *buf, int n)
		case 'r':
			exit();
			break;
		case 't':
			tcpdump();
			break;
		}
	}else if(r == 0x14){
		ctrlt++;

M port/devip.c => port/devip.c +1 -0
@@ 530,6 530,7 @@ tcpstoput(Queue *q, Block *bp)
	case Close_wait:
		qlock(tcb);
		tcb->sndcnt += blen(bp);
		print("q %d\n", blen(bp));
		if(tcb->sndq == 0)
			tcb->sndq = bp;
		else {

M port/devkprof.c => port/devkprof.c +1 -1
@@ 39,7 39,7 @@ kprofreset(void)
	ulong n;

	kprof.minpc = KTZERO;
	kprof.maxpc = (ulong)&etext;
	kprof.maxpc = (ulong)etext;
	kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
	n = kprof.nbuf*SZ;
	kprof.buf = ialloc(n, 0);

M port/devlance.c => port/devlance.c +2 -0
@@ 753,10 753,12 @@ lanceup(Etherpkt *p, int len)
		 */
		if(!canqlock(e))
			continue;

		if(e->q==0 || e->q->next->len>Streamhi || (t!=e->type && e->type!=-1)){
			qunlock(e);
			continue;
		}

		if(!waserror()){
			bp = allocb(len);
			memmove(bp->rptr, (uchar *)p, len);

M port/fault.c => port/fault.c +2 -0
@@ 66,6 66,7 @@ fixfault(Segment *s, ulong addr, int read, int doputmmu)
	switch(type) {
	default:
		panic("fault");
		break;

	case SG_TEXT:
		if(pagedout(*pg)) 			/* Demand load */


@@ 209,6 210,7 @@ pio(Segment *s, ulong addr, ulong soff, Page **p)
		ask = s->flen-soff;
		if(ask > BY2PG)
			ask = BY2PG;

		n = (*devtab[c->type].read)(c, kaddr, ask, daddr);
		if(n != ask)
			error(Eioload);

M port/lib.h => port/lib.h +3 -3
@@ 62,9 62,9 @@ extern	int	print(char*, ...);
 */
extern	long	strtol(char*, char**, int);
extern	ulong	strtoul(char*, char**, int);
extern	long	etext;
extern	long	edata;
extern	long	end;
extern	char	etext[];
extern	char	edata[];
extern	char	end[];
/*
 * Syscall data structures
 */

M port/page.c => port/page.c +1 -2
@@ 17,7 17,6 @@ struct Ptealloc
	int	pages;
}ptealloclk;

extern	long end;
ulong	hiaddr;
static Lock pglock;



@@ 115,7 114,7 @@ iallocspan(ulong n, int align, ulong crevasse)
		print("ialloc bad\n");

	if(palloc.addr0 == 0){
		region[Nregion-2].start = (((ulong)&end)&~KZERO) + conf.base0;
		region[Nregion-2].start = (((ulong)end)&~KZERO) + conf.base0;
		region[Nregion-2].end = conf.base0 + (conf.npage0<<PGSHIFT);
		region[Nregion-1].start = conf.base1;
		region[Nregion-1].end = conf.base1 + (conf.npage1<<PGSHIFT);

M port/portdat.h => port/portdat.h +2 -0
@@ 603,6 603,8 @@ struct Queue
	Rendez	r;			/* standard place to wait for flow control */
	Rendez	*rp;			/* where flow control wakeups go to */
	void	*ptr;			/* private info for the queue */
	Proc	*pp;
	Proc	*pg;
};

struct Stream

M port/proc.c => port/proc.c +4 -0
@@ 347,6 347,10 @@ wakeup(Rendez *r)
		if(p->state != Wakeme) 
			panic("wakeup: state");
		p->r = 0;
if((p->sched.pc&KZERO) != KZERO){
	spllo();
	panic("wakeup");
}
		ready(p);
	}
	unlock(r);

M port/stfcall.c => port/stfcall.c +1 -0
@@ 109,6 109,7 @@ upstream(Queue *q, ulong len)
	for(bp = bl; bp->next; bp = bp->next)
		;
	bp->flags |= S_DELIM;
if(bl->rptr[0] == 73) print("fcall Rclunk %d\n", blen(bl));
	PUTNEXT(q, bl);
}


M port/stip.c => port/stip.c +3 -2
@@ 405,6 405,7 @@ ip_reassemble(int offset, Block *bp, Etherhdr *ip)
	ushort id;
	Block *bl, **l, *last, *prev;
	int ovlap, len, fragsize, pktposn;
	int end;

	/* Check lance has handed us a contiguous buffer */
	if(bp->next)


@@ 476,7 477,7 @@ ip_reassemble(int offset, Block *bp, Etherhdr *ip)
	bp->next = *l;
	*l = bp;

	/* Check to see if suceeding segments overlap */
	/* Check to see if succeeding segments overlap */
	if(bp->next) {
		l = &bp->next;
		end = BLKFRAG(bp)->foff + BLKFRAG(bp)->flen;


@@ 491,7 492,7 @@ ip_reassemble(int offset, Block *bp, Etherhdr *ip)
				BLKFRAG(*l)->flen -= ovlap;
				(*l)->rptr += ovlap;
				break;
			}	
			}
			last = (*l)->next;
			freeb(*l);
			*l = last;

M port/stream.c => port/stream.c +60 -6
@@ 8,6 8,8 @@
#include	"devtab.h"
#include	"fcall.h"

ulong fpcs[100], refsa[100], refsf[100], apcs[100];

enum {
	Nclass=4,	/* number of block classes */
};


@@ 184,6 186,9 @@ allocb(ulong size)
{
	Block *bp;
	Bclass *bcp;
	ulong pc;

	pc = getcallerpc(((uchar*)&size) - sizeof(size));

	/*
	 *  map size to class


@@ 207,6 212,25 @@ allocb(ulong size)
	bcp->first = bp->next;
	if(bcp->first == 0)
		bcp->last = 0;

	if(bcp->size == 68) {
		int i, hole, fnd;
		fnd = 0;
		hole = -1;
		for(i = 0; i < 100; i++) {
			if(apcs[i] == pc) {
				refsa[i]++;
				fnd = 1;
				break;
			}
			if(refsa[i] == 0 && hole<0)
				hole = i;
		}
		if(fnd == 0 && hole>=0) {
			refsa[hole] = 1;
			apcs[hole] = pc;
		}
	}
	qunlock(bcp);

	/*


@@ 221,6 245,7 @@ allocb(ulong size)
	if(bp->lim-bp->rptr<size && size<4096)
		panic("allocb %lux %lux %d %ux %d", bp->lim, bp->rptr,
			size, bp->flags, bcp-bclass);
	bp->pc = pc;
	return bp;
}



@@ 236,10 261,21 @@ freeb(Block *bp)
	Bclass *bcp;
	int x;
	ulong pc;
int i;

	pc = getcallerpc(((uchar*)&bp) - sizeof(bp));
	if((bp->flags&S_CLASS) >= Nclass)		/* Check for double free */
		panic("freeb class last(%lux) this(%lux)", bp->pc, pc);

	bcp = &bclass[bp->flags & S_CLASS];
	if(bcp->size == 68) {
		for(i = 0; i < 100; i++)
			if(apcs[i] == bp->pc) {
				refsf[i]++;
				fpcs[i] = pc;
			}
	}

	bp->pc = pc;

	for(; bp; bp = nbp){


@@ 424,6 460,7 @@ putq(Queue *q, Block *bp)
	int delim;

	lock(q);
	q->pp = u->p;
	if(q->first)
		q->last->next = bp;
	else


@@ 536,6 573,7 @@ getq(Queue *q)
	Block *bp;

	lock(q);
	q->pg = u->p;
	bp = q->first;
	if(bp) {
		q->first = bp->next;


@@ 1038,6 1076,7 @@ stputq(Queue *q, Block *bp)
		delim = 1;
	} else {
		lock(q);
		q->pp = u->p;
		if(q->first)
			q->last->next = bp;
		else


@@ 1468,9 1507,10 @@ dumpblocks(Queue *q, char c)

	lock(q);
	for(bp = q->first; bp; bp = bp->next){
		print("%c%d%c", c, bp->wptr-bp->rptr, (bp->flags&S_DELIM)?'D':' ');
		for(cp = bp->rptr; cp<bp->wptr && cp<bp->rptr+10; cp++)
			print(" %uo", *cp);
		print("%c %c%d%c", c, bp->type == M_DATA ? 'd' : 'c',
			bp->wptr-bp->rptr, (bp->flags&S_DELIM)?'D':' ');
		for(cp = bp->rptr; cp<bp->wptr && cp<bp->rptr+30; cp++)
			print(" %.2x", *cp);
		print("\n");
	}
	unlock(q);


@@ 1483,18 1523,28 @@ dumpqueues(void)
	int count, qcount;
	Block *bp;
	Bclass *bcp;

int i;
	print("\n");
	qcount = 0;
	for(q = qlist; q < qlist + conf.nqueue; q++, q++){
		if(!(q->flag & QINUSE))
			continue;
		qcount++;
		print("%10s %ux  R n %d l %d f %ux r %ux", q->info->name, q,
		print("%10s %ux  R n %d l %d f %ux r %ux ",
			q->info->name, q,
			q->nb, q->len, q->flag, &(q->r));
		print("  W n %d l %d f %ux r %ux next %lux put %lux Rz %lux\n", 
			if(q->pg)
				print("get %d %s ", q->pg->pid, q->pg->text);
			if(q->pp)
				print("put %d %s ", q->pp->pid, q->pp->text);
		print("  W n %d l %d f %ux r %ux next %lux put %lux Rz %lux", 
			WR(q)->nb, WR(q)->len,
			WR(q)->flag, &(WR(q)->r), q->next, q->put, q->rp);
			if(q->pg)
				print("get %d %s ", q->pg->pid, q->pg->text);
			if(q->pp)
				print("put %d %s ", q->pp->pid, q->pp->text);
		print("\n");
		dumpblocks(q, 'R');
		dumpblocks(WR(q), 'W');
	}


@@ 1508,4 1558,8 @@ dumpqueues(void)
			bcp->made, count);
	}
	print("\n");
	for(i = 0; i < 100; i++) {
		if(refsa[i] != refsf[i])
			print("%d alloc %lux %d free %lux\n", refsa[i], apcs[i], refsf[i], fpcs[i]);
	}
}

M port/tcpinput.c => port/tcpinput.c +50 -2
@@ 42,6 42,7 @@ tcp_input(Ipconv *ipc, Block *bp)
	Ipaddr source, dest;
	char tos;
	ushort length;
	Block *f;

	DPRINT("tcp_input.\n");



@@ 290,6 291,7 @@ process:
				/* Ignore segment text */
				freeb(bp);
				break;

			case Syn_received:
			case Established:
			case Finwait1:


@@ 298,6 300,13 @@ process:
				tcb->rcvcnt += blen(bp);
				if(bp)
				if(s->readq) {
					print("bl %d ty %d\n", blen(bp), bp->rptr[0]);
					for(f = bp; bp->next; f = f->next)
						;
					if((f->flags&S_DELIM) == 0) {
						print("No delim upstream rcp");
						f->flags |= S_DELIM;
					}		
					PUTNEXT(s->readq, bp);
					bp = 0;
				}


@@ 347,7 356,9 @@ process:
				break;
			}
		}
		while(tcb->reseq != 0 && seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq)) {
		while(tcb->reseq != 0) {
			if(seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq) == 0)
				break;
			get_reseq(tcb, &tos, &seg, &bp, &length);
			if(trim(tcb, &seg, &bp, &length) == 0)
				goto gotone;


@@ 880,7 891,8 @@ htontcp(Tcp *tcph, Block *data, Tcphdr *ph)

	if(data) {
		dlen = blen(data);	
		if((data = padb(data, hdrlen + TCP_PKT)) == 0)
		data = padb(data, hdrlen + TCP_PKT);
		if(data == 0)
			return 0;
		/* If we collected blocks delimit the end of the chain */
		for(bp = data; bp->next; bp = bp->next)


@@ 977,3 989,39 @@ ntohtcp(Tcp *tcph, Block **bpp)
	}
	return hdrlen;
}

void
tcpdumpconv(Ipconv *c)
{
	if(c->tcpctl.state == Closed)
		return;

	print("%s %d -> %d.%d.%d.%d/%d snd %d recv %d una %d nxt %d ptr %d wnd %d\n",
	tcpstate[c->tcpctl.state],
	c->psrc,
	fmtaddr(c->dst),
	c->pdst,
	c->tcpctl.sndcnt,
	c->tcpctl.rcvcnt,
	c->tcpctl.snd.una,
	c->tcpctl.snd.nxt,
	c->tcpctl.snd.ptr,
	c->tcpctl.snd.wnd);
}

void
tcpdump(void)
{
	Ipifc *ep, *ifp;
	Ipconv *cp, *ecp;
	extern Ipifc *ipifc;

	ep = &ipifc[conf.ipif];
	for(ifp = ipifc; ifp < ep; ifp++)
		if(strcmp(ifp->name, "TCP") == 0) {
			ecp = &ifp->connections[conf.ip];
			for(cp = ifp->connections; cp < ecp; cp++)
				tcpdumpconv(cp);
			break;
		}
}

M port/tcpoutput.c => port/tcpoutput.c +37 -37
@@ 99,18 99,15 @@ tcp_output(Ipconv *s)
		 * in sndcnt but don't actually sit in the send queue,
		 * dupb will return one less than dsize if a FIN needs to be sent.
		 */
		dbp = 0;
		if(dsize != 0){
			if(dupb(&dbp, sndq, sent, dsize) != dsize) {
				seg.flags |= FIN;
				dsize--;
			}
			DPRINT("dupb: 1st char = %c\n", dbp->rptr[0]);
		} else
			dbp = 0;
			print("dupb: %d\n", dbp->rptr[0]);
		}

		/* If the entire send queue will now be in the pipe, set the
		 * push flag
		 */
		if(sent+dsize == qlen)
			seg.flags |= PSH;



@@ 157,14 154,33 @@ tcp_output(Ipconv *s)
				tcb->rttseq = tcb->snd.ptr;
			}
		}
		DPRINT("tcp_output: ip_send s%lux a%lux w%lux u%lux\n",
			seg.seq, seg.ack, seg.wnd, seg.up);

		print("snd: %d %x\n", blen(hbp), seg.seq);
		PUTNEXT(Ipoutput, hbp);
	}
}

void
tcprxmit(Ipconv *s)
{
	Tcpctl *tcb;

	print("tcp! rexmit\n");
	tcb = &s->tcpctl;
	qlock(tcb);
	tcb->flags |= RETRAN|FORCE;
	tcb->snd.ptr = tcb->snd.una;

	/* Reduce slowstart threshold to half current window */
	tcb->ssthresh = tcb->cwind / 2;
	tcb->ssthresh = MAX(tcb->ssthresh,tcb->mss);

	/* Shrink congestion window to 1 packet */
	tcb->cwind = tcb->mss;
	tcp_output(s);
	qunlock(tcb);
}

void
tcp_timeout(void *arg)
{
	Tcpctl *tcb;


@@ 173,11 189,17 @@ tcp_timeout(void *arg)
	s = (Ipconv *)arg;
	tcb = &s->tcpctl;

	DPRINT("Timer %lux state = %d\n", s, tcb->state);
	print("Timer %lux state = %d\n", s, tcb->state);

	switch(tcb->state){
	case Closed:
		panic("tcptimeout");
	default:
		tcb->backoff++;
		DPRINT("tcp_timeout: retransmit %d %x\n", tcb->backoff, s);
		if (tcb->backoff >= MAXBACKOFF)
			close_self(s, Etimedout);
		else 
			tcprxmit(s);
		break;

	case Time_wait:
		close_self(s, 0);


@@ 186,30 208,8 @@ tcp_timeout(void *arg)
	case Established:
		if(tcb->backoff < MAXBACKOFF)
			tcb->backoff++;
		goto retran;
	default:
		tcb->backoff++;
		DPRINT("tcp_timeout: retransmit %d %x\n", tcb->backoff, s);

		if (tcb->backoff >= MAXBACKOFF) {
			DPRINT("tcp_timeout: timeout\n");
			close_self(s, Etimedout);
		}
		else {
	retran:
			qlock(tcb);
			tcb->flags |= RETRAN|FORCE;
			tcb->snd.ptr = tcb->snd.una;

			/* Reduce slowstart threshold to half current window */
			tcb->ssthresh = tcb->cwind / 2;
			tcb->ssthresh = MAX(tcb->ssthresh,tcb->mss);

			/* Shrink congestion window to 1 packet */
			tcb->cwind = tcb->mss;
			tcp_output(s);
			qunlock(tcb);
		}
		tcprxmit(s);
		break;
	}
}



@@ 239,7 239,7 @@ tcp_acktimer(Ipconv *s)
}

void
tcprcvwin(Ipconv *s)
tcprcvwin(Ipconv *s)				/* Call with tcb locked */
{
	Tcpctl *tcb = &s->tcpctl;


M power/bboot.c => power/bboot.c +157 -434
@@ 1,37 1,6 @@
#include <u.h>
#include <libc.h>

#include <fcall.h>

#define DEFFILE "/mips/9power"
#define DEFSYS "bit!bootes"

Fcall	hdr;
char	*scmd;
char	bootfile[5*NAMELEN];
char	conffile[5*NAMELEN];
char	sys[NAMELEN];

char	buf[4*1024];

int fd;
int cfd;
int efd;

typedef
struct address {
	char *name;
	char *cmd;
} Address;

Address addr[] = {
	{ "ross", "connect 020701005eff" },
	{ "bootes", "connect 0800690203f3" },
	{ "helix", "connect 080069020427" },
	{ "spindle", "connect 0800690202df" },
	{ "r70", "connect 08002b04265d" },
	{ 0 }
};
#include "../boot/boot.h"

struct a_out_h {
	ulong	magic;			/* magic and sections */


@@ 56,399 25,162 @@ struct a_out_h {
	ulong	mystery;		/* complete mystery */
} a_out;

/*
 *  predeclared
 */
int	dkdial(char *);
int	nonetdial(char *);
int	bitdial(char *);
int	readseg(int, int, long, long, int);
int	readkernel(int);
typedef struct Net	Net;
typedef struct Flavor	Flavor;

int	printcol;

char	cputype[NAMELEN];
char	terminal[NAMELEN];
char	sys[2*NAMELEN];
char	username[NAMELEN];
char	conffile[2*NAMELEN];
char	sysname[2*NAMELEN];
char	buf[8*1024];

int mflag;
int fflag;
int kflag;

int	cache(int);
Method	*rootserver(char*);
int	readconf(int);
int	outin(char *, char *, int);
void	prerror(char *);
void	error(char *);
void	boot(int, char *);
void	readkernel(int);
int	readseg(int, int, long, long, int);

/*
 *  usage: 9b [-a] [server] [file]
 *
 *  default server is `bitbootes', default file is `/sys/src/9/mips/9'
 *  default boot file
 */
#define DEFFILE "/mips/9power"

void
main(int argc, char *argv[])
{
	int i;
	char *sysname;

	open("#c/cons", 0);
	open("#c/cons", 1);
	open("#c/cons", 1);

	sysname = argv[0];

	argv++;
	argc--;	
	while(argc > 0){
		if(argv[0][0] == '-'){
			argc--;
			argv++;
		} else
			break;
	}

	strcpy(sys, DEFSYS);
	strcpy(bootfile, DEFFILE);
	switch(argc){
	case 1:
		strcpy(bootfile, argv[0]);
		break;
	case 2:
		strcpy(bootfile, argv[0]);
		strcpy(sys, argv[1]);
		break;
	}

	boot(0, sysname);
	for(;;){
		if(fd > 0)
			close(fd);
		if(cfd > 0)
			close(cfd);
		fd = cfd = 0;
		boot(1, sysname);
	}
}
	int fd;
	Method *mp;
	char cmd[64];
	char flags[6];
	int islocal;
	char *bootfile;

int
bitdial(char *arg)
{
	return open("#3/bit3", ORDWR);
}
	sleep(1000);

int
nonetdial(char *arg)
{
	int efd, cfd, fd;
	Address *a;
	static int mounted;
	open("#c/cons", OREAD);
	open("#c/cons", OWRITE);
	open("#c/cons", OWRITE);

	for(a = addr; a->name; a++){
		if(strcmp(a->name, arg) == 0)
			break;
	}
	if(a->name == 0){
		print("can't convert nonet address to ether address\n");
		return -1;
	}
	ARGBEGIN{
	case 'u':
		strcpy(username, ARGF());
		break;
	case 'k':
		kflag = 1;
		break;
	case 'm':
		mflag = 1;
		break;
	case 'f':
		fflag = 1;
		break;
	}ARGEND

	if(!mounted){
		/*
		 *  grab a lance channel, make it recognize ether type 0x900,
		 *  and push the nonet ethernet multiplexor onto it.
		 */
		efd = open("#l/1/ctl", 2);
		if(efd < 0){
			prerror("opening #l/1/ctl");
			return -1;
		}
		if(write(efd, "connect 0x900", sizeof("connect 0x900")-1)<0){
			close(efd);
			prerror("connect 0x900");
			return -1;
		}
		if(write(efd, "push noether", sizeof("push noether")-1)<0){
			close(efd);
			prerror("push noether");
			return -1;
		}
		if(write(efd, "config nonet", sizeof("config nonet")-1)<0){
			close(efd);
			prerror("config nonet");
			return -1;
		}
		mounted = 1;
	}
	readenv("cputype", cputype, sizeof(cputype));
	readenv("terminal", terminal, sizeof(cputype));
	readenv("sysname", sysname, sizeof(sysname));
	if(argc > 1)
		bootfile = argv[1];
	else
		bootfile = DEFFILE;

	/*
	 *  grab a nonet channel and call up the file server
	 *  pick a method and initialize it
	 */
	fd = open("#nnonet/2/data", 2);
	if(fd < 0) {
		prerror("opening #nnonet/2/data");
		return -1;
	}
	cfd = open("#nnonet/2/ctl", 2);
	if(cfd < 0){
		close(fd);
		fd = -1;
		prerror("opening #nnonet/2/ctl");
		return -1;
	}
	if(write(cfd, a->cmd, strlen(a->cmd))<0){
		close(cfd);
		close(fd);
		cfd = fd = -1;
		prerror(a->cmd);
		return -1;
	}
	return fd;
}

int
dkdial(char *arg)
{
	int fd;
	char cmd[64];
	static int mounted;

	if(!mounted){
		/*
		 *  grab the hsvme and configure it for a datakit
		 */
		efd = open("#h/ctl", 2);
		if(efd < 0){
			prerror("opening #h/ctl");
			return -1;
		}
		if(write(efd, "push dkmux", sizeof("push dkmux")-1)<0){
			close(efd);
			prerror("push dkmux");
			return -1;
		}
		if(write(efd, "config 4 256 restart dk", sizeof("config 4 256 restart dk")-1)<0){
			close(efd);
			prerror("config 4 256 restart dk");
			return -1;
		}
		mounted = 1;
		sleep(2000);		/* wait for things to settle down */
	}
	mp = rootserver(argc ? *argv : 0);
	(*mp->config)(mp);
	islocal = strcmp(mp->name, "local") == 0;

	/*
	 *  grab a datakit channel and call up the file server
	 *  connect to the root file system
	 */
	fd = open("#k/dk/5/data", 2);
	if(fd < 0) {
		prerror("opening #k/dk/5/data");
		return -1;
	}
	cfd = open("#k/dk/5/ctl", 2);
	if(cfd < 0){
		close(fd);
		fd = -1;
		prerror("opening #k/dk/5/ctl");
		return -1;
	}
	sprint(cmd, "connect %s", arg);
	if(write(cfd, cmd, strlen(cmd))<0){
		close(cfd);
		close(fd);
		cfd = fd = -1;
		prerror(cmd);
		return -1;
	}
	return fd;
}

void
boot(int ask, char *addr)
{
	int n, tries;
	char *srvname;

	if(ask){
		outin("bootfile", bootfile, sizeof(bootfile));
		outin("server", sys, sizeof(sys));
	}

	for(tries = 0; tries < 5; tries++){
		fd = -1;
		if(strncmp(sys, "bit!", 4) == 0)
			fd = bitdial(srvname = &sys[4]);
		else if(strncmp(sys, "dk!", 3) == 0)
			fd = dkdial(srvname = &sys[3]);
		else if(strncmp(sys, "nonet!", 6) == 0)
			fd = nonetdial(srvname = &sys[6]);
		else
			fd = nonetdial(srvname = sys);
		if(fd >= 0)
			break;
		print("can't connect, retrying...\n");
		sleep(1000);
	}
	if(fd < 0){
		print("can't connect\n");
		return;
	}

	print("nop...");
	hdr.type = Tnop;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n){
		print("n = %d\n", n);
		prerror("write nop");
		return;
	}
  reread:
	n = read(fd, buf, sizeof buf);
	if(n <= 0){
		prerror("read nop");
		return;
	}
	if(n == 2)
		goto reread;
	if(convM2S(buf, &hdr, n) == 0) {
		print("n = %d; buf = %.2x %.2x %.2x %.2x\n",
			n, buf[0], buf[1], buf[2], buf[3]);
		prerror("format nop");
		return;
	}
	if(hdr.type != Rnop){
		prerror("not Rnop");
		return;
	}
	if(hdr.tag != NOTAG){
		prerror("tag not NOTAG");
		return;
	}

	print("session...");
	hdr.type = Tsession;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n){
		prerror("write session");
		return;
	}
	n = read(fd, buf, sizeof buf);
	if(n <= 0){
		prerror("read session");
		return;
	}
	if(convM2S(buf, &hdr, n) == 0){
		prerror("format session");
		return;
	}
	if(hdr.tag != NOTAG){
		prerror("tag not NOTAG");
		return;
	}
	if(hdr.type == Rerror){
		fprint(2, "boot: error %s\n", hdr.ename);
		return;
	}
	if(hdr.type != Rsession){
		prerror("not Rsession");
		return;
	fd = (*mp->connect)();
	if(fd < 0)
		fatal("can't connect to file server");
	if(!islocal){
		nop(fd);
		session(fd);
		if(cfs)
			fd = (*cfs)(fd);
	}

	print("mount...");
	if(bind("/", "/", MREPL) < 0){
		prerror("bind");
		return;
	}
	if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0){
		prerror("mount");
		return;
	}
	/*
	 *  create the name space, mount the root fs
	 */
	if(bind("/", "/", MREPL) < 0)
		fatal("bind");
	if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0)
		fatal("mount");
	close(fd);

	sprint(conffile, "/mips/conf/%s", addr);
	/*
	 *  open the configuration file and read it
	 *  into the kernel
	 */
	sprint(conffile, "/mips/conf/%s", sysname);
	print("%s...", conffile);
	while((fd = open(conffile, OREAD)) < 0){
	while((fd = open(conffile, OREAD)) < 0)
		outin("conffile", conffile, sizeof(conffile));
	}
	if(readconf(fd) < 0)
		prerror("readconf");
		fatal("readconf");
	close(fd);

	/*
	 *  read in real kernel
	 */
	print("%s...", bootfile);
	while((fd = open(bootfile, OREAD)) < 0){
	while((fd = open(bootfile, OREAD)) < 0)
		outin("bootfile", bootfile, sizeof(bootfile));
	}
	readkernel(fd);
	prerror("couldn't read kernel");
}

/*
 *  print error
 */
void
prerror(char *s)
{
	char buf[64];

	errstr(buf);
	fprint(2, "boot: %s: %s\n", s, buf);
}

/*
 *  print error and exit
 */
void
error(char *s)
{
	char buf[64];

	errstr(buf);
	fprint(2, "boot: %s: %s\n", s, buf);
	exits(0);
	fatal("couldn't read kernel");
}

/*
 *  lookup the address for a system
 *  ask user from whence cometh the root file system
 */
Address *
lookup(char *arg)
Method*
rootserver(char *arg)
{
	Address *a;
	char prompt[256];
	char reply[64];
	Method *mp;
	char *cp;
	int n;

	if(strcmp(arg, "?")==0 || strcmp(arg, "help")==0){
		for(a = addr; a->name; a++)
			print("%s\n", a->name);
		return 0;
	}
	for(a = addr; a->name; a++){
		if(strcmp(a->name, arg) == 0)
			return a;
	}
	return 0;
}
	mp = method;
	n = sprint(prompt, "root is from (%s", mp->name);
	for(mp++; mp->name; mp++)
		n += sprint(prompt+n, ", %s", mp->name);
	sprint(prompt+n, ")");

/*
 *  read a segment into memory
 */
int
readseg(int in, int out, long inoff, long outoff, int len)
{
	long	n, i;

	if(seek(in, inoff, 0) < 0){
		prerror("seeking bootfile");
		return -1;
	}
	if(seek(out, outoff, 0) != outoff){
		prerror("seeking #b/mem");
		return -1;
	}
	for(; len > 0; len -= n){
		if((n = read(in, buf, sizeof buf)) <= 0){
			prerror("reading bootfile");
			return -1;
		}
		if(write(out, buf, n) != n){
			prerror("writing #b/mem");
			return -1;
		}
	if(arg)
		strcpy(reply, arg);
	else
		strcpy(reply, method->name);
	for(;;){
		if(arg == 0 || mflag)
			outin(prompt, reply, sizeof(reply));
		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;
	}
	return 0;
}

/*
 *  set a configuration value
 */


/*
 *  read the configuration


@@ 472,10 204,8 @@ readconf(int fd)
	 *  write into 4 meg - 4k
	 */
	bfd = open("#b/mem", OWRITE);
	if(bfd < 0){
		prerror("can't open #b/mem");
		return;
	}
	if(bfd < 0)
		fatal("can't open #b/mem");
	x = 0x80000000 | 4*1024*1024 - 4*1024;
	if(seek(bfd, x, 0) != x){
		close(bfd);


@@ 489,76 219,69 @@ readconf(int fd)
	close(bfd);
	return 0;
}

/*
 *  read the kernel into memory and jump to it
 */
int
void
readkernel(int fd)
{
	int n;
	int bfd;

	bfd = open("#b/mem", OWRITE);
	if(bfd < 0){
		prerror("can't open #b/mem");
		return;
	}
	if(bfd < 0)
		fatal("can't open #b/mem");

	n = read(fd, &a_out, sizeof(a_out));
	if(n <= 0){
		prerror("can't read boot file");
		close(bfd);
		return;
	}
	if(n <= 0)
		fatal("can't read boot file");

	print("\n%d", a_out.text);
	if(readseg(fd, bfd, 20*4, a_out.textva, a_out.text)<0){
		prerror("can't read boot file");
		close(bfd);
		return;
	}
	if(readseg(fd, bfd, 20*4, a_out.textva, a_out.text)<0)
		fatal("can't read boot file");
	print("+%d", a_out.data);
	if(readseg(fd, bfd, 20*4 + a_out.text, a_out.textva + a_out.text, a_out.data)<0){
		prerror("can't read boot file");
		close(bfd);
		return;
	}
	if(readseg(fd, bfd, 20*4 + a_out.text, a_out.textva + a_out.text, a_out.data)<0)
		fatal("can't read boot file");
	print("+%d", a_out.bss);

	close(bfd);
	bfd = open("#b/boot", OWRITE);
	if(bfd < 0){
		prerror("can't open #b/boot");
		return;
	}
	if(bfd < 0)
		fatal("can't open #b/boot");
	
	print(" entry: 0x%ux\n", a_out.entryva);
	sleep(1000);
	if(write(bfd, &a_out.entryva, sizeof a_out.entryva) != sizeof a_out.entryva){
		prerror("can't start kernel");
		close(bfd);
	}

	return;
	if(write(bfd, &a_out.entryva, sizeof a_out.entryva) != sizeof a_out.entryva)
		fatal("can't start kernel");
}

/*
 *  prompt and get input
 *  read a segment into memory
 */
int
outin(char *prompt, char *def, int len)
readseg(int in, int out, long inoff, long outoff, int len)
{
	int n;
	long	n, i;

	do{
		print("%s[%s]: ", prompt, def);
		n = read(0, buf, len);
	}while(n==0);
	if(n < 0)
		error("can't read #c/cons; please reboot");
	if(n != 1){
		buf[n-1] = 0;
		strcpy(def, buf);
	if(seek(in, inoff, 0) < 0){
		warning("seeking bootfile");
		return -1;
	}
	return n;
	if(seek(out, outoff, 0) != outoff){
		warning("seeking #b/mem");
		return -1;
	}
	for(; len > 0; len -= n){
		if((n = read(in, buf, sizeof buf)) <= 0){
			warning("reading bootfile");
			return -1;
		}
		if(write(out, buf, n) != n){
			warning("writing #b/mem");
			return -1;
		}
	}
	return 0;
}


D power/boot.c => power/boot.c +0 -477
@@ 1,477 0,0 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>

#define DEFSYS "cyc!bootes"
#define DEFFILE "/mips/9"

Fcall	hdr;
char	*scmd;

char	buf[4*1024];
char	bootfile[5*NAMELEN];
char	sys[NAMELEN];

int	printcol;		/* so we can use the kernel's small print */

int fd;
int cfd;
int efd;
int setkey;

/*
 *  predeclared
 */
int	outin(char *, char *, int);
void	prerror(char *);
void	error(char *);
void	boot(int);
int	dkdial(char *);
int	bitdial(char *);
int	preamble(int);
void	srvcreate(char*, int);
void	settime(void);
void	key(void);
int	passwd(char*, int);
int	passtokey(char*, char*, int);

/*
 *  usage: 9b [-mp] [server] [file]
 *
 *  default server is `bitbootes', default file is `/mips/9'
 */
void
main(int argc, char *argv[])
{
	int i;
	int manual=0;

	open("#c/cons", OREAD);
	open("#c/cons", OWRITE);
	open("#c/cons", OWRITE);

	argv++;
	argc--;	

	while(argc > 0){
		if(argv[0][0] == '-'){
			if(argv[0][1] == 'm')
				manual = 1;
			else if(argv[0][1] == 'k')
				setkey = 1;
			argc--;
			argv++;
		} else
			break;
	}

	strcpy(sys, DEFSYS);
	strcpy(bootfile, DEFFILE);
	switch(argc){
	case 1:
		strcpy(bootfile, argv[0]);
		break;
	case 2:
		strcpy(bootfile, argv[0]);
		strcpy(sys, argv[1]);
		break;
	}

	key();
	boot(manual);
	for(;;){
		if(fd > 0)
			close(fd);
		if(cfd > 0)
			close(cfd);
		fd = cfd = 0;
		boot(1);
	}
}

int
bitdial(char *arg)
{
	USED(arg);
	return open("#3/bit3", ORDWR);
}

int
dkdial(char *arg)
{
	int fd;
	char cmd[64];
	static int mounted;

	if(!mounted){
		/*
		 *  grab the hsvme and configure it for a datakit
		 */
		efd = open("#h/ctl", ORDWR);
		if(efd < 0){
			prerror("opening #h/ctl");
			return -1;
		}
		if(write(efd, "push dkmux", sizeof("push dkmux")-1)<0){
			close(efd);
			prerror("push dkmux");
			return -1;
		}
		if(write(efd, "config 4 256 restart dk", sizeof("config 4 256 restart dk")-1)<0){
			close(efd);
			prerror("config 4 256 restart dk");
			return -1;
		}
		mounted = 1;
		sleep(2000);		/* wait for things to settle down */
	}

	/*
	 *  grab a datakit channel and call up the file server
	 */
	fd = open("#k/dk/5/data", ORDWR);
	if(fd < 0) {
		prerror("opening #k/dk/5/data");
		return -1;
	}
	cfd = open("#k/dk/5/ctl", ORDWR);
	if(cfd < 0){
		close(fd);
		prerror("opening #k/dk/5/ctl");
		return -1;
	}
	sprint(cmd, "connect %s", arg);
	if(write(cfd, cmd, strlen(cmd))<0){
		close(cfd);
		close(fd);
		prerror(cmd);
		return -1;
	}
	return fd;
}

int
hotdial(char *arg)
{
	USED(arg);
	return open("#H/hotrod", ORDWR);
}

int
preamble(int fd)
{
	int n;

	print("nop...");
	hdr.type = Tnop;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n){
		print("n = %d\n", n);
		prerror("write nop");
		return 0;
	}
  reread:
	n = read(fd, buf, sizeof buf);
	if(n <= 0){
		prerror("read nop");
		return 0;
	}
	if(n == 2)
		goto reread;
	if(convM2S(buf, &hdr, n) == 0) {
		print("n = %d; buf = %.2x %.2x %.2x %.2x\n",
			n, buf[0], buf[1], buf[2], buf[3]);
		prerror("format nop");
		return 0;
	}
	if(hdr.type != Rnop){
		prerror("not Rnop");
		return 0;
	}
	if(hdr.tag != NOTAG){
		prerror("tag not NOTAG");
		return 0;
	}

	print("session...");
	hdr.type = Tsession;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n){
		prerror("write session");
		return 0;
	}
	n = read(fd, buf, sizeof buf);
	if(n <= 0){
		prerror("read session");
		return 0;
	}
	if(convM2S(buf, &hdr, n) == 0){
		prerror("format session");
		return 0;
	}
	if(hdr.tag != NOTAG){
		prerror("tag not NOTAG");
		return 0;
	}
	if(hdr.type == Rerror){
		fprint(2, "boot: error %s\n", hdr.ename);
		return 0;
	}
	if(hdr.type != Rsession){
		prerror("not Rsession");
		return 0;
	}
	return 1;
}

void
boot(int ask)
{
	int n, f, tries;

	if(ask)
		outin("server", sys, sizeof(sys));

	for(tries = 0; tries < 5; tries++){
		fd = -1;
		if(strncmp(sys, "bit!", 4) == 0)
			fd = bitdial(&sys[4]);
		else if(strncmp(sys, "cyc!", 4) == 0)
			fd = hotdial(&sys[4]);
		else if(strncmp(sys, "dk!", 3) == 0)
			fd = dkdial(&sys[3]);
		if(fd >= 0)
			break;
		print("can't connect, retrying...\n");
		sleep(1000);
	}
	if(fd < 0){
		print("can't connect\n");
		return;
	}

	if(!preamble(fd))
		return;

	srvcreate("boot", fd);
	srvcreate("bootes", fd);

	print("mount...");
	if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0)
		error("mount");

	settime();

	print("success\n");

	if(ask){
		execl("/mips/init", "init", "-mc", 0);
	} else {
		execl("/mips/init", "init", "-c", 0);
	}
	error("/mips/init");
}

/*
 *  print error
 */
void
prerror(char *s)
{
	char buf[64];

	errstr(buf);
	fprint(2, "boot: %s: %s\n", s, buf);
}

/*
 *  print error and exit
 */
void
error(char *s)
{
	char buf[64];

	errstr(buf);
	fprint(2, "boot: %s: %s\n", s, buf);
	exits(0);
}

/*
 *  prompt and get input
 */
int
outin(char *prompt, char *def, int len)
{
	int n;
	char buf[256];

	do{
		print("%s[%s]: ", prompt, def);
		n = read(0, buf, len);
	}while(n==0);
	if(n < 0)
		error("can't read #c/cons; please reboot");
	if(n != 1){
		buf[n-1] = 0;
		strcpy(def, buf);
	}
	return n;
}

void
srvcreate(char *name, int fd)
{
	char *srvname;
	int f;

	srvname = strrchr(name, '/');
	if(srvname)
		srvname++;
	else
		srvname = name;

	sprint(buf, "#s/%s", srvname);
	f = create(buf, 1, 0666);
	if(f < 0)
		error("create");
	sprint(buf, "%d", fd);
	if(write(f, buf, strlen(buf)) != strlen(buf))
		error("write");
	close(f);
}

void
settime(void)
{
	char dirbuf[DIRLEN];
	Dir dir;
	int f;

	print("time...");
	/*
	 *  set the time from the access time of the root
	 *  of the file server
	 */
	f = open("#s/boot", ORDWR);
	if(f < 0)
		return;
	if(mount(f, "/n/boot", MREPL, "", "") < 0){
		close(f);
		return;
	}
	close(f);
	if(stat("/n/boot", dirbuf) < 0)
		error("stat");
	convM2D(dirbuf, &dir);
	sprint(dirbuf, "%ld", dir.atime);
	unmount(0, "/n/boot");
	f = open("#c/time", OWRITE);
	write(f, dirbuf, strlen(dirbuf));
	close(f);
}

void
key(void)
{
	char password[20], key[7];
	int prompt, fd;

	prompt = setkey;
	fd = open("#r/nvram", ORDWR);
	if(fd < 0){
		prompt = 1;
		prerror("can't open nvram");
	}
	if(prompt){
		do
			if(passwd(password, sizeof password) < 0){
				prerror("can't read cons");
				return;
			}
		while(!passtokey(key, password, strlen(password)));
	}else if(seek(fd, 1024+900, 0) < 0 || read(fd, key, 7) != 7){
		close(fd);
		prerror("can't read key from nvram");
	}
	if(setkey && (seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7)){
		close(fd);
		prerror("can't write key to nvram");
	}
	close(fd);
	fd = open("#c/key", OWRITE);
	if(fd < 0)
		prerror("can't open key");
	else if(write(fd, key, 7) != 7)
		prerror("can't write key");
	close(fd);
}

int
passwd(char *p, int len)
{
	char c;
	int i, n, fd;

	fd = open("#c/consctl", OWRITE);
	if(fd < 0)
		return -1;
	write(fd, "rawon", 5);
 Prompt:		
	print("password: ");
	n = 0;
	for(;;){
		do{
			i = read(0, &c, 1);
			if(i < 0){
				close(fd);
				return -1;
			}
		}while(i == 0);
		switch(c){
		case '\n':
			p[n] = '\0';
			close(fd);
			print("\n");
			return 0;
		case '\b':
			if(n > 0)
				n--;
			break;
		case 'u' - 'a' + 1:		/* cntrl-u */
			print("\n");
			goto Prompt;
		default:
			if(n < len - 1)
				p[n++] = c;
			break;
		}
	}
}

int
passtokey(char *key, char *p, int n)
{
	uchar t[10];
	int c;

	memset(t, ' ', sizeof t);
	if(n < 5)
		return 0;
	if(n > 10)
		n = 10;
	strncpy((char*)t, p, n);
	if(n >= 9){
		c = p[8] & 0xf;
		if(n == 10)
			c += p[9] << 4;
		for(n = 0; n < 8; n++)
			if(c & (1 << n))
				t[n] -= ' ';
	}
	for(n = 0; n < 7; n++)
		key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1)));
	return 1;
}

M power/l.s => power/l.s +1 -1
@@ 151,7 151,7 @@ TEXT	gotolabel(SB), $-4

TEXT	getcallerpc(SB), $0

	MOVW	4(SP), R1
	MOVW	0(SP), R1
	RET

TEXT	gotopc(SB), $8

M power/trap.c => power/trap.c +7 -2
@@ 340,8 340,11 @@ dumpstack(void)
	if(u)
		for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
			v = *(ulong*)l;
			if(KTZERO < v && v < (ulong)&etext)
			if(KTZERO < v && v < (ulong)&etext){
				print("%lux=%lux\n", l, v);
				prflush();
				delay(250);
			}
		}
}



@@ 357,8 360,10 @@ dumpregs(Ureg *ur)
	else
		print("registers for kernel\n");
	l = &ur->status;
	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2){
		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
		prflush();
	}
}

/*