]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/boot/pc/sub.c
9boot: replace strrchr() call with a loop and strchr() for ignoring bang path prefixes
[plan9front.git] / sys / src / boot / pc / sub.c
index c12f29a012610f82f820d129d7ce487721624ae9..470d31c39ed7e1a3f65db813e53c1573f0caa521 100644 (file)
@@ -4,9 +4,10 @@
 #include "mem.h"
 
 void
-memset(void *p, int v, int n)
+memset(void *dst, int v, int n)
 {
-       uchar *d = p;
+       uchar *d = dst;
+
        while(n > 0){
                *d++ = v;
                n--;
@@ -18,9 +19,15 @@ memmove(void *dst, void *src, int n)
 {
        uchar *d = dst;
        uchar *s = src;
-       while(n > 0){
-               *d++ = *s++;
-               n--;
+
+       if(d < s){
+               while(n-- > 0)
+                       *d++ = *s++;
+       } else if(d > s){
+               s += n;
+               d += n;
+               while(n-- > 0)
+                       *--d = *--s;
        }
 }
 
@@ -30,8 +37,11 @@ memcmp(void *src, void *dst, int n)
        uchar *d = dst;
        uchar *s = src;
        int r = 0;
-       while((n > 0) && (r = (*d++ - *s++)) == 0)
-               n--;
+
+       while(n-- > 0)
+               if(r = (*d++ - *s++))
+                       break;
+
        return r;
 }
 
@@ -39,8 +49,10 @@ int
 strlen(char *s)
 {
        char *p = s;
+
        while(*p)
                p++;
+
        return p - s;
 }
 
@@ -50,17 +62,8 @@ strchr(char *s, int c)
        for(; *s; s++)
                if(*s == c)
                        return s;
-       return 0;
-}
 
-char*
-strrchr(char *s, int c)
-{
-       char *r;
-       r = 0;
-       while(s = strchr(s, c))
-               r = s++;
-       return r;
+       return 0;
 }
 
 void
@@ -75,13 +78,20 @@ readn(void *f, void *data, int len)
 {
        uchar *p, *e;
 
+       putc(' ');
        p = data;
        e = p + len;
        while(p < e){
+               if(((ulong)p & 0xF000) == 0){
+                       putc('\b');
+                       putc(hex[((ulong)p>>16)&0xF]);
+               }
                if((len = read(f, p, e - p)) <= 0)
                        break;
                p += len;
        }
+       putc('\b');
+
        return p - (uchar*)data;
 }
 
@@ -100,7 +110,7 @@ readline(void *f, char buf[64])
                                putc(*p = getc());
                                if(*p == '\r')
                                        putc('\n');
-                               else if(*p == 0x08 && p > buf){
+                               else if(*p == '\b' && p > buf){
                                        p--;
                                        continue;
                                }
@@ -116,61 +126,242 @@ readline(void *f, char buf[64])
                        p--;
        }while(p == buf);
        *p = 0;
+
        return p - buf;
 }
 
+static int
+timeout(int ms)
+{
+       while(ms > 0){
+               if(gotc())
+                       return 1;
+               usleep(100000);
+               ms -= 100;
+       }
+       return 0;
+}
+
+#define BOOTLINE       ((char*)CONFADDR)
+#define BOOTLINELEN    64
+#define BOOTARGS       ((char*)(CONFADDR+BOOTLINELEN))
+#define        BOOTARGSLEN     (4096-0x200-BOOTLINELEN)
+
+char *confend;
+
+static void apmconf(int);
+static void e820conf(void);
+
+static int
+delconf(char *s)
+{
+       char *p, *e;
+
+       for(p = BOOTARGS; p < confend; p = e){
+               for(e = p+1; e < confend; e++){
+                       if(*e == '\n'){
+                               e++;
+                               break;
+                       }
+               }
+               if(!memcmp(p, s, strlen(s))){
+                       memmove(p, e, confend - e);
+                       confend -= e - p;
+                       *confend = 0;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 char*
 configure(void *f, char *path)
 {
-       char line[64], *p, *kern;
-       int inblock, n;
+       char line[64], *kern, *s, *p;
+       int inblock, nowait, n;
 
 Clear:
        kern = 0;
+       nowait = 1;
        inblock = 0;
-       p = (char*)(CONFADDR & ~0xF0000000UL);
-       memset(p, 0, 0xE00);
-       p += 64;
+
+       memset(BOOTLINE, 0, BOOTLINELEN);
+
+       confend = BOOTARGS;
+       memset(confend, 0, BOOTARGSLEN);
+
+       e820conf();
 Loop:
-       while((n = readline(f, line)) > 0){
+       while(readline(f, line) > 0){
                if(*line == 0 || strchr("#;=", *line))
                        continue;
                if(*line == '['){
                        inblock = memcmp("[common]", line, 8);
                        continue;
                }
-               if(memcmp("clear", line, 6) == 0){
-                       print("ok\r\n");
-                       goto Clear;
-               }
-               if(memcmp("boot", line, 5) == 0)
+               if(!memcmp("boot", line, 5)){
+                       nowait=1;
                        break;
-               if(inblock || !strrchr(line, '='))
+               }
+               if(!memcmp("wait", line, 5)){
+                       nowait=0;
                        continue;
-               print(line); print(crnl);
-               if(memcmp("bootfile=", line, 9) == 0)
-                       memmove(kern = path, line+9, 1 + n-9);
-               memmove(p, line, n); p += n;
-               *p++ = '\n';
+               }
+               if(!memcmp("clear", line, 5)){
+                       if(line[5] == 0){
+                               print("ok");
+                               print(crnl);
+                               goto Clear;
+                       } else if(line[5] == ' ' && delconf(line+6)){
+                               print("ok");
+                               print(crnl);
+                       }
+                       continue;
+               }
+               if(inblock || (p = strchr(line, '=')) == nil)
+                       continue;
+               *p++ = 0;
+               delconf(line);
+               if(!memcmp("apm", line, 3)){
+                       apmconf('0' - line[3]);
+                       continue;
+               }
+               if(!memcmp("bootfile", line, 8))
+                       memmove(kern = path, p, strlen(p)+1);
+
+               s = confend;
+               memmove(confend, line, n = strlen(line)); confend += n;
+               *confend++ = '=';
+               memmove(confend, p, n = strlen(p)); confend += n;
+               *confend = 0;
+
+               print(s); print(crnl);
+
+               *confend++ = '\n';
+               *confend = 0;
        }
-       *p = 0;
+
        if(f){
                close(f);
                f = 0;
+
+               if(kern && (nowait==0 || timeout(1000)))
+                       goto Loop;
        }
+
        if(!kern){
                print("no bootfile\r\n");
                goto Loop;
        }
-       for(n=0; n<10000; n++)
-               if(gotc())
-                       goto Loop;
-       if(p = strrchr(kern, '!'))
+       while(p = strchr(kern, '!'))
                kern = p+1;
+
        return kern;
 }
 
 
+static void
+hexfmt(char *s, int i, ulong a)
+{
+       s += i;
+       while(i > 0){
+               *--s = hex[a&15];
+               a >>= 4;
+               i--;
+       }
+}
+
+static void
+addconfx(char *s, int w, ulong v)
+{
+       int n;
+
+       n = strlen(s);
+       memmove(confend, s, n);
+       hexfmt(confend+n, w, v);
+       confend += n+w;
+       *confend = 0;
+}
+
+void apm(int id);
+
+static void
+apmconf(int id)
+{
+       uchar *a;
+       char *s;
+
+       a = (uchar*)CONFADDR;
+       memset(a, 0, 20);
+
+       apm(id);
+       if(memcmp(a, "APM", 4))
+               return;
+
+       s = confend;
+
+       addconfx("apm", 1, id);
+       addconfx("=ax=", 4, *((ushort*)(a+4)));
+       addconfx(" ebx=", 8, *((ulong*)(a+12)));
+       addconfx(" cx=", 4, *((ushort*)(a+6)));
+       addconfx(" dx=", 4, *((ushort*)(a+8)));
+       addconfx(" di=", 4, *((ushort*)(a+10)));
+       addconfx(" esi=", 8, *((ulong*)(a+16)));
+
+       print(s); print(crnl);
+
+       *confend++ = '\n';
+       *confend = 0;
+}
+
+ulong e820(ulong bx, void *p);
+
+static void
+e820conf(void)
+{
+       struct {
+               uvlong  base;
+               uvlong  len;
+               ulong   typ;
+               ulong   ext;
+       } e;
+       uvlong v;
+       ulong bx;
+       char *s;
+
+       bx=0;
+       s = confend;
+
+       do{
+               bx = e820(bx, &e);
+               if(e.typ == 1 && e.len != 0 && (e.ext & 3) == 1){
+                       if(confend == s){
+                               /* single entry <= 1MB is useless */
+                               if(bx == 0 && e.len <= 0x100000)
+                                       break;
+                               memmove(confend, "e820=", 5);
+                               confend += 5;
+                       }
+                       v = e.base;
+                       addconfx("", 8, v>>32);
+                       addconfx("", 8, v&0xffffffff);
+                       v += e.len;
+                       addconfx(" ", 8, v>>32);
+                       addconfx("", 8, v&0xffffffff);
+                       *confend++ = ' ';
+               }
+       } while(bx);
+
+       if(confend == s)
+               return;
+
+       *confend = 0;
+       print(s); print(crnl);
+
+       *confend++ = '\n';
+       *confend = 0;
+}
+
 static ushort
 beswab(ushort s)
 {
@@ -189,28 +380,41 @@ beswal(ulong l)
        return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
 }
 
+void a20(void);
+
 char*
 bootkern(void *f)
 {
-       uchar *e, *d;
+       uchar *e, *d, *t;
+       ulong n;
        Exec ex;
-       int n;
 
        a20();
+
        if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
                return "bad header";
        if(beswal(ex.magic) != I_MAGIC)
                return "bad magic";
+
        e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
+       t = e;
        n = beswal(ex.text);
-       if(readn(f, e, n) != n)
+
+       if(readn(f, t, n) != n)
                goto Error;
-       d = (uchar*)(((ulong)e + n + 0xFFF) & ~0xFFFUL);
+       d = (uchar*)PGROUND((ulong)t + n);
        n = beswal(ex.data);
+
        if(readn(f, d, n) != n)
                goto Error;
        close(f);
+       unload();
+
+       print("boot");
+       print(crnl);
+
        jump(e);
+
 Error:         
        return "i/o error";
 }