]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/archacpi.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / archacpi.c
index 644df59b9242ef830196897465ef2b7107bb98bc..3c020b84feec275c9936175f766ab826d8ecb97c 100644 (file)
@@ -4,6 +4,7 @@
 #include "dat.h"
 #include "fns.h"
 #include "io.h"
+#include "../port/error.h"
 
 #include "mp.h"
 
@@ -74,6 +75,34 @@ tbldlen(Tbl *t){
        return get32(t->len) - Tblsz;
 }
 
+static long
+memcheck(uintptr pa, long len)
+{
+       int i;
+       uintptr pe;
+       Confmem *cm;
+
+       if(len <= 0)
+               return len;
+       pe = pa + len-1;
+       if(pe < pa){
+               len = -pa;
+               pe = pa + len-1;
+       }
+       if(pa < PADDR(CPU0END))
+               return 0;
+       if(pe >= PADDR(KTZERO) && pa < PADDR(end))
+               return PADDR(KTZERO) - pa;
+       for(i=0; i<nelem(conf.mem); i++){
+               cm = &conf.mem[i];
+               if(cm->npage == 0)
+                       continue;
+               if(pe >= cm->base && pa <= cm->base + cm->npage*BY2PG - 1)
+                       return cm->base - pa;
+       }
+       return len;
+}
+
 static void
 maptable(uvlong xpa)
 {
@@ -84,8 +113,9 @@ maptable(uvlong xpa)
        int i;
 
        pa = xpa;
-       if((uvlong)pa != xpa || pa == 0)
+       if((uvlong)pa != xpa || pa == 0 || pa+7 < pa)
                return;
+               
        if(ntblpa >= nelem(tblpa) || ntblmap >= nelem(tblmap))
                return;
 
@@ -95,13 +125,17 @@ maptable(uvlong xpa)
        }
        tblpa[ntblpa++] = pa;
 
+       memreserve(pa, 8);
        if((t = vmap(pa, 8)) == nil)
                return;
        l = get32(t->len);
-       if(l < Tblsz){
+       if(l < Tblsz
+       || l >= 0x10000000
+       || pa+l-1 < pa){
                vunmap(t, 8);
                return;
        }
+       memreserve(pa, l);
        vunmap(t, 8);
        if((t = vmap(pa, l)) == nil)
                return;
@@ -141,9 +175,10 @@ maptables(void)
                return;
        if(!checksum(rsd, 20))
                maptable(get32(rsd->raddr));
-       if(rsd->rev >= 2)
+       if(rsd->rev >= 2){
                if(!checksum(rsd, 36))
                        maptable(get64(rsd->xaddr));
+       }
 }
 
 static Apic*
@@ -260,7 +295,10 @@ pcibusno(void *dot)
        if((x = amlwalk(dot, "^_BBN")) == nil)
                if((x = amlwalk(dot, "^_ADR")) == nil)
                        return -1;
-       adr = amlint(amlval(x));
+       p = nil;
+       if(amleval(x, "", &p) < 0)
+               return -1;
+       adr = amlint(p);
        /* if root bridge, then we are done here */
        if(id != nil && (strcmp(id, "PNP0A03")==0 || strcmp(id, "PNP0A08")==0))
                return adr;
@@ -282,7 +320,7 @@ static int
 pciaddr(void *dot)
 {
        int adr, bno;
-       void *x;
+       void *x, *p;
 
        for(;;){
                if((x = amlwalk(dot, "_ADR")) == nil){
@@ -294,9 +332,10 @@ pciaddr(void *dot)
                }
                if((bno = pcibusno(x)) < 0)
                        break;
-               if((x = amlval(x)) == nil)
+               p = nil;
+               if(amleval(x, "", &p) < 0)
                        break;
-               adr = amlint(x);
+               adr = amlint(p);
                return MKBUS(BusPCI, bno, adr>>16, adr&0xFFFF);
        }
        return -1;
@@ -477,6 +516,46 @@ enumec(void *dot, void *)
        return 1;
 }
 
+static long
+readmem(Chan*, void *v, long n, vlong o)
+{
+       uintptr pa = (uintptr)o;
+       void *t;
+
+       if((n = memcheck(pa, n)) <= 0)
+               return 0;
+       if((t = vmap(pa, n)) == nil)
+               error(Enovmem);
+       if(waserror()){
+               vunmap(t, n);
+               nexterror();
+       }
+       memmove(v, t, n);
+       vunmap(t, n);
+       poperror();
+       return n;
+}
+
+static long
+writemem(Chan*, void *v, long n, vlong o)
+{
+       uintptr pa = (uintptr)o;
+       void *t;
+
+       if(memcheck(pa, n) != n)
+               error(Eio);
+       if((t = vmap(pa, n)) == nil)
+               error(Enovmem);
+       if(waserror()){
+               vunmap(t, n);
+               nexterror();
+       }
+       memmove(t, v, n);
+       vunmap(t, n);
+       poperror();
+       return n;
+}
+
 static void
 acpiinit(void)
 {
@@ -487,14 +566,13 @@ acpiinit(void)
        ulong lapicbase;
        int machno, i, c;
 
-       maptables();
-
        amlinit();
 
        /* load DSDT */
        for(i=0; i<ntblmap; i++){
                t = tblmap[i];
                if(memcmp(t->sig, "DSDT", 4) == 0){
+                       amlintmask = (~0ULL) >> (t->rev <= 1)*32;
                        amlload(t->data, tbldlen(t));
                        break;
                }
@@ -606,6 +684,9 @@ Foundapic:
                }
        }
 
+       /* find embedded controller */
+       amlenum(amlroot, "_HID", enumec, nil);
+
        /* look for PCI interrupt mappings */
        amlenum(amlroot, "_PRT", enumprt, nil);
 
@@ -613,9 +694,6 @@ Foundapic:
        for(i=0; i<16; i++)
                addirq(i, BusISA, 0, i, 0);
 
-       /* find embedded controller */
-       amlenum(amlroot, "_HID", enumec, nil);
-
        /* free the AML interpreter */
        amlexit();
 
@@ -707,14 +785,18 @@ identify(void)
                return 1;
        pa = (uintptr)strtoull(cp, nil, 16);
        if(pa <= 1)
-               rsd = sigsearch("RSD PTR ");
-       else
+               rsd = rsdsearch();
+       else {
+               memreserve(pa, sizeof(Rsd));
                rsd = vmap(pa, sizeof(Rsd));
+       }
        if(rsd == nil)
                return 1;
        if(checksum(rsd, 20) && checksum(rsd, 36))
                return 1;
+       maptables();
        addarchfile("acpitbls", 0444, readtbls, nil);
+       addarchfile("acpimem", 0600, readmem, writemem);
        if(strcmp(cp, "0") == 0)
                return 1;
        if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
@@ -761,6 +843,42 @@ readpcicfg(Amlio *io, void *data, int n, int offset)
        return i;
 }
 
+static int
+readec(Amlio *io, void *data, int n, int off)
+{
+       int port, v;
+       uchar *p;
+
+       USED(io);
+       if(off < 0 || off >= 256)
+               return 0;
+       if(off+n > 256)
+               n = 256 - off;
+       p = data;
+       for(port = off; port < off+n; port++){
+               if((v = ecread(port)) < 0)
+                       break;
+               *p++ = v;
+       }
+       return n;
+}
+
+static int
+writeec(Amlio *io, void *data, int n, int off)
+{
+       int port;
+       uchar *p;
+
+       USED(io);
+       if(off < 0 || off+n > 256)
+               return -1;
+       p = data;
+       for(port = off; port < off+n; port++)
+               if(ecwrite(port, *p++) < 0)
+                       break;
+       return n;
+}
+
 static int
 writepcicfg(Amlio *io, void *data, int n, int offset)
 {
@@ -852,6 +970,11 @@ amlmapio(Amlio *io)
                print("amlmapio: address space %x not implemented\n", io->space);
                break;
        case MemSpace:
+               if(memcheck(io->off, io->len) != io->len){
+                       print("amlmapio: [%#p-%#p) overlaps usable memory\n",
+                               (uintptr)io->off, (uintptr)(io->off+io->len));
+                       break;
+               }
                if((io->va = vmap(io->off, io->len)) == nil){
                        print("amlmapio: vmap failed\n");
                        break;
@@ -879,6 +1002,10 @@ amlmapio(Amlio *io)
                io->read = readpcicfg;
                io->write = writepcicfg;
                return 0;
+       case EbctlSpace:
+               io->read = readec;
+               io->write = writeec;
+               return 0;
        }
        print("amlmapio: mapping %N failed\n", io->name);
        return -1;