123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530 |
- #include "u.h"
- #include "lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "dosfs.h"
- /*
- * Where configuration info is left for the loaded programme.
- * This will turn into a structure as more is done by the boot loader
- * (e.g. why parse the .ini file twice?).
- * 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.
- */
- #define BOOTLINELEN 64
- #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
- #define BOOTARGSLEN (3584-0x200-BOOTLINELEN)
- #define MAXCONF 100
- static char *confname[MAXCONF];
- static char *confval[MAXCONF];
- static int nconf;
- extern char **ini;
- typedef struct {
- char* name;
- int start;
- int end;
- } Mblock;
- typedef struct {
- char* tag;
- Mblock* mb;
- } Mitem;
- static Mblock mblock[MAXCONF];
- static int nmblock;
- static Mitem mitem[MAXCONF];
- static int nmitem;
- static char* mdefault;
- static char mdefaultbuf[10];
- static int mtimeout;
- static char*
- comma(char* line, char** residue)
- {
- char *q, *r;
- if((q = strchr(line, ',')) != nil){
- *q++ = 0;
- if(*q == ' ')
- q++;
- }
- *residue = q;
- if((r = strchr(line, ' ')) != nil)
- *r = 0;
- if(*line == ' ')
- line++;
- return line;
- }
- static Mblock*
- findblock(char* name, char** residue)
- {
- int i;
- char *p;
- p = comma(name, residue);
- for(i = 0; i < nmblock; i++){
- if(strcmp(p, mblock[i].name) == 0)
- return &mblock[i];
- }
- return nil;
- }
- static Mitem*
- finditem(char* name, char** residue)
- {
- int i;
- char *p;
- p = comma(name, residue);
- for(i = 0; i < nmitem; i++){
- if(strcmp(p, mitem[i].mb->name) == 0)
- return &mitem[i];
- }
- return nil;
- }
- static void
- parsemenu(char* str, char* scratch, int len)
- {
- Mitem *mi;
- Mblock *mb, *menu;
- char buf[20], *p, *q, *line[MAXCONF];
- int i, inblock, n, show;
- inblock = 0;
- menu = nil;
- memmove(scratch, str, len);
- n = getfields(scratch, line, MAXCONF, '\n');
- if(n >= MAXCONF)
- print("warning: possibly too many lines in plan9.ini\n");
- for(i = 0; i < n; i++){
- p = line[i];
- if(inblock && *p == '['){
- mblock[nmblock].end = i;
- if(strcmp(mblock[nmblock].name, "menu") == 0)
- menu = &mblock[nmblock];
- nmblock++;
- inblock = 0;
- }
- if(*p == '['){
- if(nmblock == 0 && i != 0){
- mblock[nmblock].name = "common";
- mblock[nmblock].start = 0;
- mblock[nmblock].end = i;
- nmblock++;
- }
- q = strchr(p+1, ']');
- if(q == nil || *(q+1) != 0){
- print("malformed menu block header - %s\n", p);
- return;
- }
- *q = 0;
- mblock[nmblock].name = p+1;
- mblock[nmblock].start = i+1;
- inblock = 1;
- }
- }
- if(inblock){
- mblock[nmblock].end = i;
- nmblock++;
- }
- if(menu == nil)
- return;
- if(nmblock < 2){
- print("incomplete menu specification\n");
- return;
- }
- for(i = menu->start; i < menu->end; i++){
- p = line[i];
- if(cistrncmp(p, "menuitem=", 9) == 0){
- p += 9;
- if((mb = findblock(p, &q)) == nil){
- print("no block for menuitem %s\n", p);
- return;
- }
- if(q != nil)
- mitem[nmitem].tag = q;
- else
- mitem[nmitem].tag = mb->name;
- mitem[nmitem].mb = mb;
- nmitem++;
- }
- else if(cistrncmp(p, "menudefault=", 12) == 0){
- p += 12;
- if((mi = finditem(p, &q)) == nil){
- print("no item for menudefault %s\n", p);
- return;
- }
- if(q != nil)
- mtimeout = strtol(q, 0, 0);
- sprint(mdefaultbuf, "%ld", mi-mitem+1);
- mdefault = mdefaultbuf;
- }
- else if(cistrncmp(p, "menuconsole=", 12) == 0){
- p += 12;
- p = comma(p, &q);
- consinit(p, q);
- }
- else{
- print("invalid line in [menu] block - %s\n", p);
- return;
- }
- }
- again:
- print("\nPlan 9 Startup Menu:\n====================\n");
- for(i = 0; i < nmitem; i++)
- print(" %d. %s\n", i+1, mitem[i].tag);
- for(;;){
- getstr("Selection", buf, sizeof(buf), mdefault, mtimeout);
- mtimeout = 0;
- i = strtol(buf, &p, 0)-1;
- if(i < 0 || i >= nmitem)
- continue;
- switch(*p){
- case 'p':
- case 'P':
- show = 1;
- print("\n");
- break;
- case 0:
- show = 0;
- break;
- default:
- continue;
-
- }
- mi = &mitem[i];
-
- p = str;
- p += sprint(p, "menuitem=%s\n", mi->mb->name);
- for(i = 0; i < nmblock; i++){
- mb = &mblock[i];
- if(mi->mb != mb && cistrcmp(mb->name, "common") != 0)
- continue;
- for(n = mb->start; n < mb->end; n++)
- p += sprint(p, "%s\n", line[n]);
- }
- if(show){
- for(q = str; q < p; q += i){
- if((i = print(q)) <= 0)
- break;
- }
- goto again;
- }
- break;
- }
- print("\n");
- }
- /*
- static void
- msleep(int msec)
- {
- ulong start;
- for(start = m->ticks; TK2MS(m->ticks - start) < msec; )
- ;
- }
- */
- void
- readlsconf(void)
- {
- uchar *p;
- p = (uchar*)CONFADDR;
- for(;;) {
- if(strcmp((char*)p, "APM") == 0){
- apm.haveinfo = 1;
- apm.ax = *(ushort*)(p+4);
- apm.cx = *(ushort*)(p+6);
- apm.dx = *(ushort*)(p+8);
- apm.di = *(ushort*)(p+10);
- apm.ebx = *(ulong*)(p+12);
- apm.esi = *(ulong*)(p+16);
- print("apm ax=%x cx=%x dx=%x di=%x ebx=%x esi=%x\n",
- apm.ax, apm.cx, apm.dx, apm.di, apm.ebx, apm.esi);
- p += 20;
- continue;
- }
- break;
- }
- }
- char*
- getconf(char *name)
- {
- int i, n, nmatch;
- char buf[20];
- nmatch = 0;
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- nmatch++;
- switch(nmatch) {
- default:
- print("\n");
- nmatch = 0;
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- print("%d. %s\n", ++nmatch, confval[i]);
- print("%d. none of the above\n", ++nmatch);
- do {
- getstr(name, buf, sizeof(buf), nil, 0);
- n = atoi(buf);
- } while(n < 1 || n > nmatch);
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- if(--n == 0)
- return confval[i];
- break;
- case 1:
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- return confval[i];
- break;
- case 0:
- break;
- }
- return nil;
- }
- void
- addconf(char *fmt, ...)
- {
- donprint(BOOTARGS+strlen(BOOTARGS), BOOTARGS+BOOTARGSLEN, fmt, (&fmt+1));
- }
- void
- changeconf(char *fmt, ...)
- {
- char *p, *q, pref[20], buf[128];
- donprint(buf, buf+sizeof buf, fmt, (&fmt+1));
- strncpy(pref+1, buf, 19);
- pref[19] = '\0';
- if(p = strchr(pref, '='))
- *(p+1) = '\0';
- else
- print("warning: did not change %s in plan9.ini\n", buf);
- /* find old line by looking for \nwhat= */
- pref[0] = '\n';
- if(strncmp(BOOTARGS, pref+1, strlen(pref+1)) == 0)
- p = BOOTARGS;
- else if(p = strstr(BOOTARGS, pref))
- p++;
- else
- p = nil;
- /* move rest of args up, deleting what= line. */
- if(p != nil && (q = strchr(p, '\n')) != nil)
- memmove(p, q+1, strlen(q+1)+1);
- /* add replacement to end */
- addconf("%s", buf);
- }
- /*
- * read configuration file
- */
- static char inibuf[BOOTARGSLEN];
- static char id[8] = "ZORT 0\r\n";
- int
- dotini(Dos *dos)
- {
- Dosfile rc;
- int blankline, i, incomment, inspace, n;
- char *cp, *p, *q, *line[MAXCONF];
- if(dosstat(dos, *ini, &rc) <= 0)
- return -1;
- cp = inibuf;
- *cp = 0;
- n = dosread(&rc, cp, BOOTARGSLEN-1);
- if(n <= 0)
- return -1;
- cp[n] = 0;
- /*
- * Strip out '\r', change '\t' -> ' '.
- * Change runs of spaces into single spaces.
- * Strip out trailing spaces, blank lines.
- *
- * We do this before we make the copy so that if we
- * need to change the copy, it is already fairly clean.
- * The main need is in the case when plan9.ini has been
- * padded with lots of trailing spaces, as is the case
- * for those created during a distribution install.
- */
- p = cp;
- blankline = 1;
- incomment = inspace = 0;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- if(*q == ' '){
- inspace = 1;
- continue;
- }
- if(*q == '\n'){
- if(!blankline){
- if(!incomment)
- *p++ = '\n';
- blankline = 1;
- }
- incomment = inspace = 0;
- continue;
- }
- if(inspace){
- if(!blankline && !incomment)
- *p++ = ' ';
- inspace = 0;
- }
- if(blankline && *q == '#')
- incomment = 1;
- blankline = 0;
- if(!incomment)
- *p++ = *q;
- }
- if(p > cp && p[-1] != '\n')
- *p++ = '\n';
- *p++ = 0;
- n = p-cp;
- parsemenu(cp, BOOTARGS, n);
- /*
- * Keep a copy.
- * We could change this to pass the parsed strings
- * to the booted programme instead of the raw
- * string, then it only gets done once.
- */
- if(strncmp(cp, id, sizeof(id))){
- memmove(BOOTARGS, id, sizeof(id));
- if(n+1+sizeof(id) >= BOOTARGSLEN)
- n -= sizeof(id);
- memmove(BOOTARGS+sizeof(id), cp, n+1);
- }
- else
- memmove(BOOTARGS, cp, n+1);
- n = getfields(cp, line, MAXCONF, '\n');
- for(i = 0; i < n; i++){
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
- return 0;
- }
- static int
- parseether(uchar *to, char *from)
- {
- char nip[4];
- char *p;
- int i;
- p = from;
- while(*p == ' ')
- ++p;
- for(i = 0; i < 6; i++){
- if(*p == 0)
- return -1;
- nip[0] = *p++;
- if(*p == 0)
- return -1;
- nip[1] = *p++;
- nip[2] = 0;
- to[i] = strtoul(nip, 0, 16);
- if(*p == ':')
- p++;
- }
- return 0;
- }
- int
- isaconfig(char *class, int ctlrno, ISAConf *isa)
- {
- char cc[NAMELEN], *p, *q, *r;
- int n;
- sprint(cc, "%s%d", class, ctlrno);
- for(n = 0; n < nconf; n++){
- if(cistrncmp(confname[n], cc, NAMELEN))
- continue;
- isa->nopt = 0;
- p = confval[n];
- while(*p){
- while(*p == ' ' || *p == '\t')
- p++;
- if(*p == '\0')
- break;
- if(cistrncmp(p, "type=", 5) == 0){
- p += 5;
- for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
- if(*p == '\0' || *p == ' ' || *p == '\t')
- break;
- *q = *p++;
- }
- *q = '\0';
- }
- else if(cistrncmp(p, "port=", 5) == 0)
- isa->port = strtoul(p+5, &p, 0);
- else if(cistrncmp(p, "irq=", 4) == 0)
- isa->irq = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "mem=", 4) == 0)
- isa->mem = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "size=", 5) == 0)
- isa->size = strtoul(p+5, &p, 0);
- else if(cistrncmp(p, "ea=", 3) == 0){
- if(parseether(isa->ea, p+3) == -1)
- memset(isa->ea, 0, 6);
- }
- else if(isa->nopt < NISAOPT){
- r = isa->opt[isa->nopt];
- while(*p && *p != ' ' && *p != '\t'){
- *r++ = *p++;
- if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
- break;
- }
- *r = '\0';
- isa->nopt++;
- }
- while(*p && *p != ' ' && *p != '\t')
- p++;
- }
- return 1;
- }
- return 0;
- }
|