518 lines · 9.2 KB · C
RawDownload
#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h" #include "fs.h" /* * There are 3584 bytes available at CONFADDR. * * The low-level boot routines in l.s leave data for us at CONFADDR, * which we pick up before reading the plan9.ini file. */enum {	Maxblocks	= 10,	Maxitem		= 32,	Maxconf		= 100,	Bootlinelen	= 64,	Bootargslen	= 3584-0x200-Bootlinelen,};#define Bootargs	((char*)(CONFADDR+Bootlinelen)) typedef struct Mblock Mblock;struct Mblock {	Mblock	*next;	char	name[28];	char	v[512];}; static	Mblock	*blktab[Maxblocks];static	Mblock	*conftab[Maxconf];static	Mblock	*curblk;static	int	nblock;extern	char	**ini; 	void	parseini(char*); static Mblock*lookblock(char *s){	int i; 	for(i = 0; i < nblock; i++)		if(strcmp(s, blktab[i]->name) == 0)			return blktab[i];	return nil;} static Mblock*newblock(char *s){	char buf[28];	int l;	Mblock *b; 	if(nblock == Maxblocks)		return nil;	if(s[0] != '[' || (l = strlen(++s)) >= 28)		return nil;	if(s[--l] != ']' || l < 1)		return nil;	memmove(buf, s, l);	buf[l] = 0;	if(b = lookblock(buf))		return curblk = b;	b = blktab[nblock++] = malloc(sizeof *b);	memmove(b->name, buf, l + 1);	return curblk = b;} static Mblock*common(void){	return newblock("[common]");} static Mblock*lookitem(char *s){	Mblock *b; 	for(b = curblk; b; b = b->next)		if(strcmp(b->name, s) == 0)			return b;	return nil;} static Mblock*newitem0(Mblock *m){	Mblock *b; 	for(b = curblk; b->next; b = b->next)		;	b->next = m;	return m;} static Mblock*newitem(char *s){	char *p;	int l;	Mblock *m; 	p = strchr(s, '=');	if(p == nil || (l = p - s) == 0 || l >= 28)		return nil;	if(s[l - 1] == ' ' && --l == 0)		return nil;	if(*++p && *p == ' ')		p++;	m = malloc(sizeof *m);	memmove(m->name, s, l);	m->name[l] = 0;	snprint(m->v, sizeof m->v, "%s", p);	return newitem0(m);} static intvarsep(int c){	return strchr("!/= {}()", c) != nil;} static voiddovar(Mblock *b0, Mblock *b, char *p, char *e){	char *p0, *q, buf[28], tok[80];	int l, dol;	Mblock *c, *m; 	while(*p){		p0 = p;		if(dol = *p == '$')			p++;		for(q = p; *q; q++)			if(varsep(*q))				break;		l = snprint(buf, sizeof buf, "%.*s", (int)(q-p), p);		if(0)			print("dovar %s[%s] %s\n", dol? "$ ": "", buf, q);		m = nil;		if(q > p && dol)			for(c = b0; c != nil && c != b; c = c->next)				if(cistrcmp(c->name, buf) == 0)					m = c;		if(m){			snprint(tok, sizeof tok, "%s%s", m->v, q);			seprint(p0, e, "%s", tok);		}else{			p += l;			if(varsep(*p) && *p)				p++;		}	}} static voidvarsubst(Mblock *b0){	Mblock *b; 	for(b = b0; b != nil; b = b->next)		dovar(b0, b, b->v, b->v + sizeof b->v);} voidchangeconf(char *name, int append, char *fmt, ...){	char *p, *e, buf[128];	int m;	va_list arg;	Mblock *b; 	va_start(arg, fmt);	vseprint(buf, buf+sizeof buf, fmt, arg);	va_end(arg); 	for(b = common(); b != nil; b = b->next){		m = cistrcmp(name, b->name) == 0;		if(!m && b->next == nil && !append){			b->next = malloc(sizeof *b);			memmove(b->next->name, name, strlen(name));		}else if(m){			if(!append)				b->v[0] = 0;			p = b->v;			e = p + sizeof b->v;			p += strlen(b->v);			seprint(p, e, "%s", buf);			dovar(common(), b, p, e);		}	}} static Mblock**buildvtab(Mblock *b0){	int i;	Mblock *b, **t; 	t = conftab;	i = 0;	for(b = b0; b != nil && i < Maxconf-1; b = b->next)		t[i++] = b;	t[i] = 0;	return t;} char*getconf(char *name){	int i, n, nmatch;	char *r, buf[128], itab[Maxconf];	Mblock **t, *b; redux:	t = buildvtab(common());	nmatch = 0;	for(i = 0; t[i] != nil; i++)		if(cistrcmp(name, t[i]->name) == 0)			itab[nmatch++] = i;	n = nmatch;	if(n > 1){		print("\n");		for(i = 0; i < nmatch; i++)			print("%d. %s\n", i + 1, t[itab[i]]->v);		print("a. add an item\n");		do{			getstr(name, buf, sizeof buf, nil, 0);			n = strtol(buf, &r, 0);			if(buf[0] == 'a' && buf[1] == ' '){				changeconf(" ", 0, buf + 2);				if(b = lookitem(" "))					snprint(b->name, sizeof b->name, "%s", name);				goto redux;			}		}while(n < 1 || n > i);	}	r = nil;	if(n != 0)		r = t[itab[n-1]]->v;	for(i = 0; i < nmatch; i++)		if(i != n && i > 0)			t[itab[i]-1]->next = t[itab[i]+1];	return r;} static intcomma(char *s, char **f){	char *r;	int i, n;	static char buf[128]; 	f[0] = f[1] = "";	snprint(buf, sizeof buf, "%s", s);	n = getfields(buf, f, 2, ',');	for(i = 0; i < n; i++){		if(f[i][0] == ' ')			f[i]++;		r = f[i] + strlen(f[i]);		if(r > f[i] && r[-1] == ' ')			r[-1] = 0;	}	return n;} static char*pritem(Mblock *b){	static char buf[128]; 	if(b->v[0] == 0)		snprint(buf, sizeof buf, "[%s]", b->name);	else		snprint(buf, sizeof buf, "%s=%s", b->name, b->v);	return buf;}	static voidmenu(void){	char *r, *f[2], buf[80], buf1[10];	int i, n, tmout, item, dfltno;	Mblock *m, *b, *p, *dflt, *mtab[Maxblocks], *ptab[Maxblocks]; 	if((b = lookblock("menu")) == nil)		return;	dflt = nil;	tmout = 0;	item = 0;	for(p = b->next; p != nil; p = p->next){		n = comma(p->v, f);		m = lookblock(f[0]);		if(cistrcmp(p->name, "menuitem") == 0){			if(n != 2 || m == nil)				print("invalid block %s\n", f[0]);			else{				ptab[item] = p;				mtab[item++] = m;			}		}else if(cistrcmp(p->name, "menudefault") == 0){			if(m == nil)				print("invalid menudefault %s\n", f[0]);			else{				dflt = m;				tmout = strtol(f[1], 0, 0);			}		}else if(cistrcmp(p->name, "menuconsole") == 0)			consinit(f[0]);		else			print("invalid line in [menu] %s=%s\n", p->name, p->v);	}redux:	print("\nPlan 9 Startup Menu:\n====================\n");	dfltno = 0;	for(i = 0; i < item; i++){		comma(ptab[i]->v, f);		print("    %d. %s\n", i + 1, f[1]);		if(mtab[i] == dflt)			dfltno = i + 1;	}	if(dfltno == 0 && dflt != nil){		print("bad default [%s]\n", dflt->name);		tmout = 0;	}	for(;;){		snprint(buf1, sizeof buf1, "%d", dfltno);		getstr("Selection", buf, sizeof buf, dfltno>0? buf1: nil, tmout);		tmout = 0;		i = strtoul(buf, &r, 0);		if(*r == 'm' && r[1] == 0)			goto redux;		print("\n");		if(*r == 'a' && r[1] == ' ')			parseini(r + 2);		else if(*r == 'p' || *r == 'P'){			for(p = common(); p; p = p->next)				print("%s\n", pritem(p));			if(i > 0 && i < item)				for(p = mtab[i-1]; p; p = p->next)					print("%s\n", pritem(p));		}else if(*r == 0 && i <= item){			m = mtab[i-1];			common();			newitem0(m->next);	/* chain 'em up */			if(b = lookblock("commontail"))				newitem0(b->next);			comma(ptab[i-1]->v, f);			changeconf("menuitem", 0, "%s", f[0]);			return;		}	}} voidbuildconf(void){	char *p, *e;	Mblock *b; 	p = Bootargs;	e = p + Bootargslen;	for(b = common()->next; b; b = b->next)		if(b->v[0])			p = seprint(p, e, "%s=%s\n", b->name, b->v);} static char*sanitize(char *s){	char *p, *e, *tok[20];	int m, j, b;	static char buf[128]; 	b = 1;	for(p = s; *p; p++)		if(*p == '\t' || *p == '\r')			*p = ' ';		else if(b && *p == '#')			*p = 0;		else			b = 0;	m = getfields(s, tok, nelem(tok), ' ');	buf[0] = 0;	if(m > 0){		j = 0;		e = buf + sizeof buf;		for(p = buf;;){			p = seprint(p, e, "%s", tok[j]);			if(++j == m)				break;			p = seprint(p, e, " ");		}	}	return buf;} voidparseini(char *s){	char *p, *line[Maxconf];	int n, i; 	common();	n = getfields(s, line, nelem(line), '\n');	for(i = 0; i < n; i++){		p = sanitize(line[i]);		if(*p == '[')			newblock(p);		else if(*p)			newitem(p);	}} intdotini(Fs *fs, char *name, char *devstr){	char *p;	int n;	File rc; 	if(fswalk(fs, *ini, &rc) <= 0)		return -1;	p = Bootargs;	if((n = fsread(&rc, p, Bootargslen-2)) <= 0)		return -1;	p[n] = '\n';	p[n+1] = 0; //	common();	changeconf("bootdev", 0, "%s", name);	changeconf("bootpath", 0, "%s/$bootdev", devstr);	parseini(p);	menu();	varsubst(common());	return 0;} static char*match(char *s, char *p){	if(cistrncmp(s, p, strlen(p)) == 0)		return s + strlen(p);	return nil;} static char*copyto(char *p, char *t, int nt, int term){	char *e; 	e = t + nt;	for(; *p != 0 && *p != term && t < e;)		*t++ = *p++;	*t = 0;	return p;} intisaconfig(char *class, int ctlrno, ISAConf *isa){	char cc[NAMELEN], *p, *r; 	snprint(cc, sizeof cc, "%s%d", class, ctlrno);	if((p = getconf(cc)) == nil)		return 0;	for(;;){		if(*p== ' ')			p++;		if(*p == 0)			break;		if(r = match(p, "type="))			p = copyto(r, isa->type, sizeof isa->type, ' ');		else if(r = match(p, "port="))			isa->port = strtoul(r, &p, 0);		else if(r = match(p, "irq="))			isa->irq = strtoul(r, &p, 0);		else if(r = match(p, "mem="))			isa->mem = strtoul(r, &p, 0);		else if(r = match(p, "size="))			isa->size = strtoul(r, &p, 0);		else if(r = match(p, "ea=")){			if(parseether(isa->ea, r) == -1)				memset(isa->ea, 0, 6);		}else if(isa->nopt < NISAOPT)			p = copyto(p, isa->opt[isa->nopt++], ISAOPTLEN, ' ');		while(*p && *p != ' ')			p++;	}	return 0;	} voidreadlsconf(void){

Lines 1–500 of 518.