125210b06SDavid du Colombier /*
225210b06SDavid du Colombier * parse plan.ini or /cfg/pxe/%E file into low memory
325210b06SDavid du Colombier */
425210b06SDavid du Colombier #include "u.h"
525210b06SDavid du Colombier #include "../port/lib.h"
625210b06SDavid du Colombier #include "mem.h"
725210b06SDavid du Colombier #include "dat.h"
825210b06SDavid du Colombier #include "fns.h"
925210b06SDavid du Colombier #include "io.h"
1025210b06SDavid du Colombier #include "ureg.h"
1125210b06SDavid du Colombier #include "pool.h"
1225210b06SDavid du Colombier #include "../port/netif.h"
1325210b06SDavid du Colombier #include "../ip/ip.h"
1425210b06SDavid du Colombier #include "pxe.h"
1525210b06SDavid du Colombier
1625210b06SDavid du Colombier typedef struct {
1725210b06SDavid du Colombier char* name;
1825210b06SDavid du Colombier int start;
1925210b06SDavid du Colombier int end;
2025210b06SDavid du Colombier } Mblock;
2125210b06SDavid du Colombier
2225210b06SDavid du Colombier typedef struct {
2325210b06SDavid du Colombier char* tag;
2425210b06SDavid du Colombier Mblock* mb;
2525210b06SDavid du Colombier } Mitem;
2625210b06SDavid du Colombier
27c1e5ebd3SDavid du Colombier Chan *conschan;
28c1e5ebd3SDavid du Colombier
2925210b06SDavid du Colombier static Mblock mblock[MAXCONF];
3025210b06SDavid du Colombier static int nmblock;
3125210b06SDavid du Colombier static Mitem mitem[MAXCONF];
3225210b06SDavid du Colombier static int nmitem;
3325210b06SDavid du Colombier static char* mdefault;
3425210b06SDavid du Colombier static char mdefaultbuf[10];
3525210b06SDavid du Colombier static int mtimeout;
3625210b06SDavid du Colombier
3725210b06SDavid du Colombier static char*
comma(char * line,char ** residue)3825210b06SDavid du Colombier comma(char* line, char** residue)
3925210b06SDavid du Colombier {
4025210b06SDavid du Colombier char *q, *r;
4125210b06SDavid du Colombier
4225210b06SDavid du Colombier if((q = strchr(line, ',')) != nil){
4325210b06SDavid du Colombier *q++ = 0;
4425210b06SDavid du Colombier if(*q == ' ')
4525210b06SDavid du Colombier q++;
4625210b06SDavid du Colombier }
4725210b06SDavid du Colombier *residue = q;
4825210b06SDavid du Colombier
4925210b06SDavid du Colombier if((r = strchr(line, ' ')) != nil)
5025210b06SDavid du Colombier *r = 0;
5125210b06SDavid du Colombier
5225210b06SDavid du Colombier if(*line == ' ')
5325210b06SDavid du Colombier line++;
5425210b06SDavid du Colombier return line;
5525210b06SDavid du Colombier }
5625210b06SDavid du Colombier
5725210b06SDavid du Colombier static Mblock*
findblock(char * name,char ** residue)5825210b06SDavid du Colombier findblock(char* name, char** residue)
5925210b06SDavid du Colombier {
6025210b06SDavid du Colombier int i;
6125210b06SDavid du Colombier char *p;
6225210b06SDavid du Colombier
6325210b06SDavid du Colombier p = comma(name, residue);
6425210b06SDavid du Colombier for(i = 0; i < nmblock; i++){
6525210b06SDavid du Colombier if(strcmp(p, mblock[i].name) == 0)
6625210b06SDavid du Colombier return &mblock[i];
6725210b06SDavid du Colombier }
6825210b06SDavid du Colombier return nil;
6925210b06SDavid du Colombier }
7025210b06SDavid du Colombier
7125210b06SDavid du Colombier static Mitem*
finditem(char * name,char ** residue)7225210b06SDavid du Colombier finditem(char* name, char** residue)
7325210b06SDavid du Colombier {
7425210b06SDavid du Colombier int i;
7525210b06SDavid du Colombier char *p;
7625210b06SDavid du Colombier
7725210b06SDavid du Colombier p = comma(name, residue);
7825210b06SDavid du Colombier for(i = 0; i < nmitem; i++){
7925210b06SDavid du Colombier if(strcmp(p, mitem[i].mb->name) == 0)
8025210b06SDavid du Colombier return &mitem[i];
8125210b06SDavid du Colombier }
8225210b06SDavid du Colombier return nil;
8325210b06SDavid du Colombier }
8425210b06SDavid du Colombier
8525210b06SDavid du Colombier /* timeout is in seconds */
8625210b06SDavid du Colombier int
getstr(char * prompt,char * buf,int size,char * def,int timeout)8725210b06SDavid du Colombier getstr(char *prompt, char *buf, int size, char *def, int timeout)
8825210b06SDavid du Colombier {
8925210b06SDavid du Colombier int len, isdefault;
9025210b06SDavid du Colombier static char pbuf[PRINTSIZE];
9125210b06SDavid du Colombier
9225210b06SDavid du Colombier if(conschan == nil)
93c1e5ebd3SDavid du Colombier panic("getstr: #c/cons not open");
9425210b06SDavid du Colombier buf[0] = 0;
9525210b06SDavid du Colombier isdefault = (def && *def);
9625210b06SDavid du Colombier if(isdefault == 0){
9725210b06SDavid du Colombier timeout = 0;
9825210b06SDavid du Colombier snprint(pbuf, sizeof pbuf, "%s: ", prompt);
9925210b06SDavid du Colombier }
10025210b06SDavid du Colombier else if(timeout)
10125210b06SDavid du Colombier snprint(pbuf, sizeof pbuf, "%s[default==%s (%ds timeout)]: ",
10225210b06SDavid du Colombier prompt, def, timeout);
10325210b06SDavid du Colombier else
10425210b06SDavid du Colombier snprint(pbuf, sizeof pbuf, "%s[default==%s]: ", prompt, def);
10525210b06SDavid du Colombier for (;;) {
10625210b06SDavid du Colombier print("%s", pbuf);
10725210b06SDavid du Colombier if (timeout > 0) {
10825210b06SDavid du Colombier for(timeout *= 1000; timeout > 0; timeout -= 100) {
10925210b06SDavid du Colombier if (qlen(kbdq) > 0) /* if input queued */
11025210b06SDavid du Colombier break;
111c1e5ebd3SDavid du Colombier tsleep(&up->sleep, return0, 0, 100);
11225210b06SDavid du Colombier }
11325210b06SDavid du Colombier if (timeout <= 0) { /* use default */
11425210b06SDavid du Colombier print("\n");
11525210b06SDavid du Colombier len = 0;
11625210b06SDavid du Colombier break;
11725210b06SDavid du Colombier }
11825210b06SDavid du Colombier }
11925210b06SDavid du Colombier buf[0] = '\0';
12025210b06SDavid du Colombier len = devtab[conschan->type]->read(conschan, buf, size - 1,
12125210b06SDavid du Colombier conschan->offset);
12225210b06SDavid du Colombier if(len >= 0)
12325210b06SDavid du Colombier buf[len] = '\0';
12425210b06SDavid du Colombier switch(len){
12525210b06SDavid du Colombier case 0: /* eof */
12625210b06SDavid du Colombier case 1: /* newline */
12725210b06SDavid du Colombier len = 0;
12825210b06SDavid du Colombier buf[len] = '\0';
12925210b06SDavid du Colombier if(!isdefault)
13025210b06SDavid du Colombier continue;
13125210b06SDavid du Colombier break;
13225210b06SDavid du Colombier }
13325210b06SDavid du Colombier if(len < size - 1)
13425210b06SDavid du Colombier break;
13525210b06SDavid du Colombier print("line too long\n");
13625210b06SDavid du Colombier }
13725210b06SDavid du Colombier if(len == 0 && isdefault)
13825210b06SDavid du Colombier strncpy(buf, def, size);
13925210b06SDavid du Colombier return 0;
14025210b06SDavid du Colombier }
14125210b06SDavid du Colombier
142e4575fb1SDavid du Colombier void
askbootfile(char * buf,int len,char ** bootfp,int secs,char * def)143e4575fb1SDavid du Colombier askbootfile(char *buf, int len, char **bootfp, int secs, char *def)
144e4575fb1SDavid du Colombier {
145e4575fb1SDavid du Colombier getstr("\nBoot from", buf, len, def, secs);
146e4575fb1SDavid du Colombier trimnl(buf);
147e4575fb1SDavid du Colombier if (bootfp)
148e4575fb1SDavid du Colombier kstrdup(bootfp, buf);
149e4575fb1SDavid du Colombier }
150e4575fb1SDavid du Colombier
15125210b06SDavid du Colombier int
isconf(char * name)15225210b06SDavid du Colombier isconf(char *name)
15325210b06SDavid du Colombier {
15425210b06SDavid du Colombier int i;
15525210b06SDavid du Colombier
15625210b06SDavid du Colombier for(i = 0; i < nconf; i++)
15725210b06SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
15825210b06SDavid du Colombier return 1;
15925210b06SDavid du Colombier return 0;
16025210b06SDavid du Colombier }
16125210b06SDavid du Colombier
162e4575fb1SDavid du Colombier /* result is not malloced, unlike user-mode getenv() */
16325210b06SDavid du Colombier char*
getconf(char * name)16425210b06SDavid du Colombier getconf(char *name)
16525210b06SDavid du Colombier {
16625210b06SDavid du Colombier int i, n, nmatch;
16725210b06SDavid du Colombier char buf[120];
16825210b06SDavid du Colombier
16925210b06SDavid du Colombier nmatch = 0;
17025210b06SDavid du Colombier for(i = 0; i < nconf; i++)
17125210b06SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
17225210b06SDavid du Colombier nmatch++;
17325210b06SDavid du Colombier
17425210b06SDavid du Colombier switch(nmatch) {
17525210b06SDavid du Colombier default:
17625210b06SDavid du Colombier print("\n");
17725210b06SDavid du Colombier nmatch = 0;
17825210b06SDavid du Colombier for(i = 0; i < nconf; i++)
17925210b06SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
18025210b06SDavid du Colombier print("%d. %s\n", ++nmatch, confval[i]);
18125210b06SDavid du Colombier print("%d. none of the above\n", ++nmatch);
18225210b06SDavid du Colombier do {
18325210b06SDavid du Colombier getstr(name, buf, sizeof(buf), nil, 0);
18425210b06SDavid du Colombier n = atoi(buf);
18525210b06SDavid du Colombier } while(n < 1 || n > nmatch);
18625210b06SDavid du Colombier
18725210b06SDavid du Colombier for(i = 0; i < nconf; i++)
18825210b06SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
18925210b06SDavid du Colombier if(--n == 0)
19025210b06SDavid du Colombier return confval[i];
19125210b06SDavid du Colombier break;
19225210b06SDavid du Colombier
19325210b06SDavid du Colombier case 1:
19425210b06SDavid du Colombier for(i = 0; i < nconf; i++)
19525210b06SDavid du Colombier if(cistrcmp(confname[i], name) == 0)
19625210b06SDavid du Colombier return confval[i];
19725210b06SDavid du Colombier break;
19825210b06SDavid du Colombier
19925210b06SDavid du Colombier case 0:
20025210b06SDavid du Colombier break;
20125210b06SDavid du Colombier }
20225210b06SDavid du Colombier return nil;
20325210b06SDavid du Colombier }
20425210b06SDavid du Colombier
20525210b06SDavid du Colombier static void
parsemenu(char * str,char * scratch,int len)20625210b06SDavid du Colombier parsemenu(char* str, char* scratch, int len)
20725210b06SDavid du Colombier {
20825210b06SDavid du Colombier Mitem *mi;
20925210b06SDavid du Colombier Mblock *mb, *menu;
21025210b06SDavid du Colombier char buf[20], *p, *q, *line[MAXCONF];
21125210b06SDavid du Colombier int i, inblock, n, show;
21225210b06SDavid du Colombier
21325210b06SDavid du Colombier inblock = 0;
21425210b06SDavid du Colombier menu = nil;
21525210b06SDavid du Colombier memmove(scratch, str, len);
21625210b06SDavid du Colombier n = getfields(scratch, line, MAXCONF, 0, "\n");
21725210b06SDavid du Colombier if(n >= MAXCONF)
21825210b06SDavid du Colombier print("warning: possibly too many lines in plan9.ini\n");
21925210b06SDavid du Colombier for(i = 0; i < n; i++){
22025210b06SDavid du Colombier p = line[i];
22125210b06SDavid du Colombier if(inblock && *p == '['){
22225210b06SDavid du Colombier mblock[nmblock].end = i;
22325210b06SDavid du Colombier if(strcmp(mblock[nmblock].name, "menu") == 0)
22425210b06SDavid du Colombier menu = &mblock[nmblock];
22525210b06SDavid du Colombier nmblock++;
22625210b06SDavid du Colombier inblock = 0;
22725210b06SDavid du Colombier }
22825210b06SDavid du Colombier if(*p == '['){
22925210b06SDavid du Colombier if(nmblock == 0 && i != 0){
23025210b06SDavid du Colombier mblock[nmblock].name = "common";
23125210b06SDavid du Colombier mblock[nmblock].start = 0;
23225210b06SDavid du Colombier mblock[nmblock].end = i;
23325210b06SDavid du Colombier nmblock++;
23425210b06SDavid du Colombier }
23525210b06SDavid du Colombier q = strchr(p+1, ']');
23625210b06SDavid du Colombier if(q == nil || *(q+1) != 0){
23725210b06SDavid du Colombier print("malformed menu block header - %s\n", p);
23825210b06SDavid du Colombier return;
23925210b06SDavid du Colombier }
24025210b06SDavid du Colombier *q = 0;
24125210b06SDavid du Colombier mblock[nmblock].name = p+1;
24225210b06SDavid du Colombier mblock[nmblock].start = i+1;
24325210b06SDavid du Colombier inblock = 1;
24425210b06SDavid du Colombier }
24525210b06SDavid du Colombier }
24625210b06SDavid du Colombier
24725210b06SDavid du Colombier if(inblock){
24825210b06SDavid du Colombier mblock[nmblock].end = i;
24925210b06SDavid du Colombier nmblock++;
25025210b06SDavid du Colombier }
25125210b06SDavid du Colombier if(menu == nil)
25225210b06SDavid du Colombier return;
25325210b06SDavid du Colombier if(nmblock < 2){
25425210b06SDavid du Colombier print("incomplete menu specification\n");
25525210b06SDavid du Colombier return;
25625210b06SDavid du Colombier }
25725210b06SDavid du Colombier
25825210b06SDavid du Colombier for(i = menu->start; i < menu->end; i++){
25925210b06SDavid du Colombier p = line[i];
26025210b06SDavid du Colombier if(cistrncmp(p, "menuitem=", 9) == 0){
26125210b06SDavid du Colombier p += 9;
26225210b06SDavid du Colombier if((mb = findblock(p, &q)) == nil){
26325210b06SDavid du Colombier print("no block for menuitem %s\n", p);
26425210b06SDavid du Colombier return;
26525210b06SDavid du Colombier }
26625210b06SDavid du Colombier if(q != nil)
26725210b06SDavid du Colombier mitem[nmitem].tag = q;
26825210b06SDavid du Colombier else
26925210b06SDavid du Colombier mitem[nmitem].tag = mb->name;
27025210b06SDavid du Colombier mitem[nmitem].mb = mb;
27125210b06SDavid du Colombier nmitem++;
27225210b06SDavid du Colombier }
27325210b06SDavid du Colombier else if(cistrncmp(p, "menudefault=", 12) == 0){
27425210b06SDavid du Colombier p += 12;
27525210b06SDavid du Colombier if((mi = finditem(p, &q)) == nil){
27625210b06SDavid du Colombier print("no item for menudefault %s\n", p);
27725210b06SDavid du Colombier return;
27825210b06SDavid du Colombier }
27925210b06SDavid du Colombier if(q != nil)
28025210b06SDavid du Colombier mtimeout = strtol(q, 0, 0);
28125210b06SDavid du Colombier snprint(mdefaultbuf, sizeof mdefaultbuf, "%ld",
28225210b06SDavid du Colombier mi-mitem+1);
28325210b06SDavid du Colombier mdefault = mdefaultbuf;
28425210b06SDavid du Colombier }
28525210b06SDavid du Colombier else if(cistrncmp(p, "menuconsole=", 12) == 0){
28625210b06SDavid du Colombier p += 12;
28725210b06SDavid du Colombier p = comma(p, &q);
28825210b06SDavid du Colombier i8250config(p);
28925210b06SDavid du Colombier }
29025210b06SDavid du Colombier else{
29125210b06SDavid du Colombier print("invalid line in [menu] block - %s\n", p);
29225210b06SDavid du Colombier return;
29325210b06SDavid du Colombier }
29425210b06SDavid du Colombier }
29525210b06SDavid du Colombier
29625210b06SDavid du Colombier again:
29725210b06SDavid du Colombier print("\nPlan 9 Startup Menu:\n====================\n");
29825210b06SDavid du Colombier for(i = 0; i < nmitem; i++)
29925210b06SDavid du Colombier print(" %d. %s\n", i+1, mitem[i].tag);
30025210b06SDavid du Colombier for(;;){
30125210b06SDavid du Colombier getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
30225210b06SDavid du Colombier mtimeout = 0;
30325210b06SDavid du Colombier i = strtol(buf, &p, 0)-1;
30425210b06SDavid du Colombier if(i < 0 || i >= nmitem)
30525210b06SDavid du Colombier goto again;
30625210b06SDavid du Colombier switch(*p){
30725210b06SDavid du Colombier case 'p':
30825210b06SDavid du Colombier case 'P':
30925210b06SDavid du Colombier show = 1;
31025210b06SDavid du Colombier print("\n");
31125210b06SDavid du Colombier break;
31225210b06SDavid du Colombier case 0:
31325210b06SDavid du Colombier case '\n':
31425210b06SDavid du Colombier show = 0;
31525210b06SDavid du Colombier break;
31625210b06SDavid du Colombier default:
31725210b06SDavid du Colombier continue;
31825210b06SDavid du Colombier
31925210b06SDavid du Colombier }
32025210b06SDavid du Colombier mi = &mitem[i];
32125210b06SDavid du Colombier
32225210b06SDavid du Colombier p = str;
323*426f2a32SDavid du Colombier p += snprint(p, len, "menuitem=%s\n", mi->mb->name);
32425210b06SDavid du Colombier for(i = 0; i < nmblock; i++){
32525210b06SDavid du Colombier mb = &mblock[i];
32625210b06SDavid du Colombier if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
32725210b06SDavid du Colombier continue;
32825210b06SDavid du Colombier for(n = mb->start; n < mb->end; n++)
329*426f2a32SDavid du Colombier p += snprint(p, &str[len] - p, "%s\n", line[n]);
33025210b06SDavid du Colombier }
33125210b06SDavid du Colombier
33225210b06SDavid du Colombier if(show){
33325210b06SDavid du Colombier for(q = str; q < p; q += i){
33425210b06SDavid du Colombier if((i = print(q)) <= 0)
33525210b06SDavid du Colombier break;
33625210b06SDavid du Colombier }
33725210b06SDavid du Colombier goto again;
33825210b06SDavid du Colombier }
33925210b06SDavid du Colombier break;
34025210b06SDavid du Colombier }
34125210b06SDavid du Colombier print("\n");
34225210b06SDavid du Colombier }
34325210b06SDavid du Colombier
34425210b06SDavid du Colombier /* dig out tables created by l16r.s in real mode */
34525210b06SDavid du Colombier void
readlsconf(void)34625210b06SDavid du Colombier readlsconf(void)
34725210b06SDavid du Colombier {
34825210b06SDavid du Colombier int i, n;
34925210b06SDavid du Colombier uchar *p;
35025210b06SDavid du Colombier MMap *map;
35125210b06SDavid du Colombier u64int addr, len;
35225210b06SDavid du Colombier
35325210b06SDavid du Colombier /*
35425210b06SDavid du Colombier * we could be running above 1MB, so put bios tables in low memory,
35525210b06SDavid du Colombier * not after end.
35625210b06SDavid du Colombier */
35725210b06SDavid du Colombier p = (uchar*)KADDR(BIOSTABLES);
35825210b06SDavid du Colombier for(n = 0; n < nelem(mmap); n++){
35925210b06SDavid du Colombier if(*p == 0)
36025210b06SDavid du Colombier break;
36125210b06SDavid du Colombier if(memcmp(p, "APM\0", 4) == 0){
36225210b06SDavid du Colombier p += 20;
36325210b06SDavid du Colombier continue;
36425210b06SDavid du Colombier }
36525210b06SDavid du Colombier else if(memcmp(p, "MAP\0", 4) == 0){
36625210b06SDavid du Colombier map = (MMap*)p;
36725210b06SDavid du Colombier
36825210b06SDavid du Colombier switch(map->type){
36925210b06SDavid du Colombier default:
37025210b06SDavid du Colombier if(v_flag)
37125210b06SDavid du Colombier print("type %ud", map->type);
37225210b06SDavid du Colombier break;
37325210b06SDavid du Colombier case 1:
37425210b06SDavid du Colombier if(v_flag)
37525210b06SDavid du Colombier print("Memory");
37625210b06SDavid du Colombier break;
37725210b06SDavid du Colombier case 2:
37825210b06SDavid du Colombier if(v_flag)
37925210b06SDavid du Colombier print("reserved");
38025210b06SDavid du Colombier break;
38125210b06SDavid du Colombier case 3:
38225210b06SDavid du Colombier if(v_flag)
38325210b06SDavid du Colombier print("ACPI Reclaim Memory");
38425210b06SDavid du Colombier break;
38525210b06SDavid du Colombier case 4:
38625210b06SDavid du Colombier if(v_flag)
38725210b06SDavid du Colombier print("ACPI NVS Memory");
38825210b06SDavid du Colombier break;
38925210b06SDavid du Colombier }
39025210b06SDavid du Colombier addr = (((u64int)map->base[1])<<32)|map->base[0];
39125210b06SDavid du Colombier len = (((u64int)map->length[1])<<32)|map->length[0];
39225210b06SDavid du Colombier if(v_flag)
39325210b06SDavid du Colombier print("\t%#16.16lluX %#16.16lluX (%llud)\n",
39425210b06SDavid du Colombier addr, addr+len, len);
39525210b06SDavid du Colombier
39625210b06SDavid du Colombier if(nmmap < nelem(mmap)){
39725210b06SDavid du Colombier memmove(&mmap[nmmap], map, sizeof(MMap));
39825210b06SDavid du Colombier mmap[nmmap].size = 20;
39925210b06SDavid du Colombier nmmap++;
40025210b06SDavid du Colombier }
40125210b06SDavid du Colombier p += 24;
40225210b06SDavid du Colombier continue;
40325210b06SDavid du Colombier }
40425210b06SDavid du Colombier else{
40525210b06SDavid du Colombier /* ideally we shouldn't print here */
40625210b06SDavid du Colombier print("\nweird low-memory map at %#p:\n", p);
40725210b06SDavid du Colombier for(i = 0; i < 24; i++)
40825210b06SDavid du Colombier print(" %2.2uX", *(p+i));
40925210b06SDavid du Colombier print("\n");
41025210b06SDavid du Colombier delay(5000);
41125210b06SDavid du Colombier }
41225210b06SDavid du Colombier break;
41325210b06SDavid du Colombier }
41425210b06SDavid du Colombier }
41525210b06SDavid du Colombier
41625210b06SDavid du Colombier void
addconf(char * fmt,...)41725210b06SDavid du Colombier addconf(char *fmt, ...)
41825210b06SDavid du Colombier {
41925210b06SDavid du Colombier va_list arg;
42025210b06SDavid du Colombier
42125210b06SDavid du Colombier va_start(arg, fmt);
42225210b06SDavid du Colombier vseprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, arg);
42325210b06SDavid du Colombier va_end(arg);
42425210b06SDavid du Colombier }
42525210b06SDavid du Colombier
42625210b06SDavid du Colombier void
dumpbootargs(void)42725210b06SDavid du Colombier dumpbootargs(void)
42825210b06SDavid du Colombier {
42925210b06SDavid du Colombier char *p, *nl;
43025210b06SDavid du Colombier
43125210b06SDavid du Colombier /* in the boot, we can only print PRINTSIZE (256) bytes at a time. */
43225210b06SDavid du Colombier print("boot args: ");
43325210b06SDavid du Colombier for (p = (char *)BOOTARGS; *p != '\0'; p = nl) {
43425210b06SDavid du Colombier nl = strchr(p, '\n');
43525210b06SDavid du Colombier if (nl != nil) {
43625210b06SDavid du Colombier ++nl;
43725210b06SDavid du Colombier print("%.*s", (int)(nl - p), p);
43825210b06SDavid du Colombier }
43925210b06SDavid du Colombier }
44025210b06SDavid du Colombier }
44125210b06SDavid du Colombier
44225210b06SDavid du Colombier void
changeconf(char * fmt,...)44325210b06SDavid du Colombier changeconf(char *fmt, ...)
44425210b06SDavid du Colombier {
44525210b06SDavid du Colombier va_list arg;
44625210b06SDavid du Colombier char *p, *q, pref[20], buf[128];
44725210b06SDavid du Colombier
44825210b06SDavid du Colombier va_start(arg, fmt);
44925210b06SDavid du Colombier vseprint(buf, buf+sizeof buf, fmt, arg);
45025210b06SDavid du Colombier va_end(arg);
45125210b06SDavid du Colombier
45225210b06SDavid du Colombier pref[0] = '\n';
45325210b06SDavid du Colombier strncpy(pref+1, buf, 19);
45425210b06SDavid du Colombier pref[19] = '\0';
45525210b06SDavid du Colombier if(p = strchr(pref, '='))
45625210b06SDavid du Colombier *(p+1) = '\0';
45725210b06SDavid du Colombier else
45825210b06SDavid du Colombier print("warning: did not change %s in plan9.ini\n", buf);
45925210b06SDavid du Colombier
46025210b06SDavid du Colombier /* find old line by looking for \nwhat= */
46125210b06SDavid du Colombier if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
46225210b06SDavid du Colombier p = BOOTARGS;
46325210b06SDavid du Colombier else if(p = strstr(BOOTARGS, pref))
46425210b06SDavid du Colombier p++;
46525210b06SDavid du Colombier else
46625210b06SDavid du Colombier p = nil;
46725210b06SDavid du Colombier
46825210b06SDavid du Colombier /* move rest of args up, deleting what= line. */
46925210b06SDavid du Colombier if(p != nil && (q = strchr(p, '\n')) != nil)
47025210b06SDavid du Colombier memmove(p, q+1, strlen(q+1)+1);
47125210b06SDavid du Colombier
47225210b06SDavid du Colombier /* add replacement to end */
47325210b06SDavid du Colombier addconf("%s", buf);
47425210b06SDavid du Colombier }
47525210b06SDavid du Colombier
47625210b06SDavid du Colombier /*
47725210b06SDavid du Colombier * read configuration file
47825210b06SDavid du Colombier */
47925210b06SDavid du Colombier static char id[8] = "ZORT 0\r\n";
48025210b06SDavid du Colombier
48125210b06SDavid du Colombier int
dotini(char * inibuf)48225210b06SDavid du Colombier dotini(char *inibuf)
48325210b06SDavid du Colombier {
48425210b06SDavid du Colombier int blankline, i, incomment, inspace, n;
48525210b06SDavid du Colombier char *cp, *p, *q, *line[MAXCONF];
48625210b06SDavid du Colombier
48725210b06SDavid du Colombier cp = inibuf;
48825210b06SDavid du Colombier
48925210b06SDavid du Colombier /*
49025210b06SDavid du Colombier * Strip out '\r', change '\t' -> ' '.
49125210b06SDavid du Colombier * Change runs of spaces into single spaces.
49225210b06SDavid du Colombier * Strip out trailing spaces, blank lines.
49325210b06SDavid du Colombier *
49425210b06SDavid du Colombier * We do this before we make the copy so that if we
49525210b06SDavid du Colombier * need to change the copy, it is already fairly clean.
49625210b06SDavid du Colombier * The main need is in the case when plan9.ini has been
49725210b06SDavid du Colombier * padded with lots of trailing spaces, as is the case
49825210b06SDavid du Colombier * for those created during a distribution install.
49925210b06SDavid du Colombier */
50025210b06SDavid du Colombier p = cp;
50125210b06SDavid du Colombier blankline = 1;
50225210b06SDavid du Colombier incomment = inspace = 0;
50325210b06SDavid du Colombier for(q = cp; *q; q++){
50425210b06SDavid du Colombier if(*q == '\r')
50525210b06SDavid du Colombier continue;
50625210b06SDavid du Colombier if(*q == '\t')
50725210b06SDavid du Colombier *q = ' ';
50825210b06SDavid du Colombier if(*q == ' '){
50925210b06SDavid du Colombier inspace = 1;
51025210b06SDavid du Colombier continue;
51125210b06SDavid du Colombier }
51225210b06SDavid du Colombier if(*q == '\n'){
51325210b06SDavid du Colombier if(!blankline){
51425210b06SDavid du Colombier if(!incomment)
51525210b06SDavid du Colombier *p++ = '\n';
51625210b06SDavid du Colombier blankline = 1;
51725210b06SDavid du Colombier }
51825210b06SDavid du Colombier incomment = inspace = 0;
51925210b06SDavid du Colombier continue;
52025210b06SDavid du Colombier }
52125210b06SDavid du Colombier if(inspace){
52225210b06SDavid du Colombier if(!blankline && !incomment)
52325210b06SDavid du Colombier *p++ = ' ';
52425210b06SDavid du Colombier inspace = 0;
52525210b06SDavid du Colombier }
52625210b06SDavid du Colombier if(blankline && *q == '#')
52725210b06SDavid du Colombier incomment = 1;
52825210b06SDavid du Colombier blankline = 0;
52925210b06SDavid du Colombier if(!incomment)
53025210b06SDavid du Colombier *p++ = *q;
53125210b06SDavid du Colombier }
53225210b06SDavid du Colombier if(p > cp && p[-1] != '\n')
53325210b06SDavid du Colombier *p++ = '\n';
53425210b06SDavid du Colombier *p++ = 0;
53525210b06SDavid du Colombier n = p-cp;
53625210b06SDavid du Colombier
53725210b06SDavid du Colombier parsemenu(cp, BOOTARGS, n);
53825210b06SDavid du Colombier
53925210b06SDavid du Colombier /*
54025210b06SDavid du Colombier * Keep a copy.
54125210b06SDavid du Colombier * We could change this to pass the parsed strings
54225210b06SDavid du Colombier * to the booted programme instead of the raw
54325210b06SDavid du Colombier * string, then it only gets done once.
54425210b06SDavid du Colombier */
54525210b06SDavid du Colombier if(strncmp(cp, id, sizeof(id))){
54625210b06SDavid du Colombier memmove(BOOTARGS, id, sizeof(id));
54725210b06SDavid du Colombier if(n+1+sizeof(id) >= BOOTARGSLEN)
54825210b06SDavid du Colombier n -= sizeof(id);
54925210b06SDavid du Colombier memmove(BOOTARGS+sizeof(id), cp, n+1);
55025210b06SDavid du Colombier }
55125210b06SDavid du Colombier else
55225210b06SDavid du Colombier memmove(BOOTARGS, cp, n+1);
55325210b06SDavid du Colombier
55425210b06SDavid du Colombier n = getfields(cp, line, MAXCONF, 0, "\n");
55525210b06SDavid du Colombier for(i = 0; i < n; i++){
55625210b06SDavid du Colombier cp = strchr(line[i], '=');
55725210b06SDavid du Colombier if(cp == 0)
55825210b06SDavid du Colombier continue;
55925210b06SDavid du Colombier *cp++ = 0;
56025210b06SDavid du Colombier if(cp - line[i] >= NAMELEN+1)
56125210b06SDavid du Colombier *(line[i]+NAMELEN-1) = 0;
56225210b06SDavid du Colombier confname[nconf] = line[i];
56325210b06SDavid du Colombier confval[nconf] = cp;
56425210b06SDavid du Colombier nconf++;
56525210b06SDavid du Colombier }
56625210b06SDavid du Colombier return 0;
56725210b06SDavid du Colombier }
568