summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-05-19 01:58:40 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-05-19 01:58:40 +0200
commitb44038fec0e84eece7c0143c59f3e991c55a6147 (patch)
treefe1a0360299d7091534faa69232e9a60d79a3374
parent9891d13887d66ecee6d6ae960df764d5b8dbc2df (diff)
downloadplan9front-b44038fec0e84eece7c0143c59f3e991c55a6147.tar.xz
kernel: add debug driver for dumping acpi tables
-rw-r--r--sys/src/9/pc/acpi.c219
-rw-r--r--sys/src/9/pc/pccpuf1
-rw-r--r--sys/src/9/pc/pcf1
3 files changed, 221 insertions, 0 deletions
diff --git a/sys/src/9/pc/acpi.c b/sys/src/9/pc/acpi.c
new file mode 100644
index 000000000..f50ad8c01
--- /dev/null
+++ b/sys/src/9/pc/acpi.c
@@ -0,0 +1,219 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+typedef struct Rsd Rsd;
+typedef struct Tbl Tbl;
+
+struct Rsd {
+ uchar sig[8];
+ uchar csum;
+ uchar oemid[6];
+ uchar rev;
+ uchar raddr[4];
+ uchar len[4];
+ uchar xaddr[8];
+ uchar xcsum;
+ uchar reserved[3];
+};
+
+struct Tbl {
+ uchar sig[4];
+ uchar len[4];
+ uchar rev;
+ uchar csum;
+ uchar oemid[6];
+ uchar oemtid[8];
+ uchar oemrev[4];
+ uchar cid[4];
+ uchar crev[4];
+ uchar data[];
+};
+
+static int ntbltab;
+static Tbl *tbltab[64];
+
+static ushort
+get16(uchar *p){
+ return p[1]<<8 | p[0];
+}
+
+static uint
+get32(uchar *p){
+ return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
+}
+
+static uvlong
+get64(uchar *p){
+ uvlong u;
+
+ u = get32(p+4);
+ return u<<32 | get32(p);
+}
+
+static int
+checksum(void *v, int n)
+{
+ uchar *p, s;
+
+ s = 0;
+ p = v;
+ while(n-- > 0)
+ s += *p++;
+ return s;
+}
+
+static void*
+rsdscan(uchar* addr, int len, char* sig)
+{
+ int sl;
+ uchar *e, *p;
+
+ e = addr+len;
+ sl = strlen(sig);
+ for(p = addr; p+sl < e; p += 16){
+ if(memcmp(p, sig, sl))
+ continue;
+ return p;
+ }
+ return nil;
+}
+
+static void*
+rsdsearch(char* sig)
+{
+ uintptr p;
+ uchar *bda;
+ Rsd *rsd;
+
+ /*
+ * Search for the data structure signature:
+ * 1) in the first KB of the EBDA;
+ * 2) in the BIOS ROM between 0xE0000 and 0xFFFFF.
+ */
+ if(strncmp((char*)KADDR(0xFFFD9), "EISA", 4) == 0){
+ bda = KADDR(0x400);
+ if((p = (bda[0x0F]<<8)|bda[0x0E]))
+ if(rsd = rsdscan(KADDR(p), 1024, sig))
+ return rsd;
+ }
+ return rsdscan(KADDR(0xE0000), 0x20000, sig);
+}
+
+static void
+maptable(uvlong xpa)
+{
+ uchar *p, *e;
+ Tbl *t, *a;
+ uintptr pa;
+ u32int l;
+ int i;
+
+ pa = xpa;
+ if((uvlong)pa != xpa || pa == 0)
+ return;
+ if(ntbltab >= nelem(tbltab))
+ return;
+ if((t = vmap(pa, 8)) == nil)
+ return;
+ l = get32(t->len);
+ if(l < sizeof(Tbl) || t->sig[0] == 0){
+ vunmap(t, 8);
+ return;
+ }
+ for(i=0; i<ntbltab; i++){
+ if(memcmp(tbltab[i]->sig, t->sig, sizeof(t->sig)) == 0)
+ break;
+ }
+ vunmap(t, 8);
+ if(i < ntbltab)
+ return;
+ if((a = malloc(l)) == nil)
+ return;
+ if((t = vmap(pa, l)) == nil){
+ free(a);
+ return;
+ }
+ if(checksum(t, l)){
+ vunmap(t, l);
+ free(a);
+ return;
+ }
+ memmove(a, t, l);
+ vunmap(t, l);
+
+ tbltab[ntbltab++] = t = a;
+
+ if(0) print("acpi: %llux %.4s %d\n", xpa, t->sig, l);
+
+ p = (uchar*)t;
+ e = p + l;
+ if(memcmp("RSDT", t->sig, 4) == 0){
+ for(p = t->data; p+3 < e; p += 4)
+ maptable(get32(p));
+ return;
+ }
+ if(memcmp("XSDT", t->sig, 4) == 0){
+ for(p = t->data; p+7 < e; p += 8)
+ maptable(get64(p));
+ return;
+ }
+ if(memcmp("FACP", t->sig, 4) == 0){
+ if(l < 44)
+ return;
+ maptable(get32(p + 40));
+ if(l < 148)
+ return;
+ maptable(get64(p + 140));
+ return;
+ }
+}
+
+static long
+readtbls(Chan*, void *v, long n, vlong o)
+{
+ int i, l, m;
+ uchar *p;
+ Tbl *t;
+
+ p = v;
+ for(i=0; n > 0 && i < ntbltab; i++){
+ t = tbltab[i];
+ l = get32(t->len);
+ if(o >= l){
+ o -= l;
+ continue;
+ }
+ m = l - o;
+ if(m > n)
+ m = n;
+ memmove(p, (uchar*)t + o, m);
+ p += m;
+ n -= m;
+ o = 0;
+ }
+ return p - (uchar*)v;
+}
+
+void
+acpilink(void)
+{
+ Rsd *r;
+
+ /*
+ * this is a debug driver to dump the acpi tables.
+ * do nothing unless *acpi gets explicitly enabled.
+ */
+ if(getconf("*acpi") == nil)
+ return;
+ if((r = rsdsearch("RSD PTR ")) == nil)
+ return;
+ if(checksum(r, 20) == 0)
+ maptable(get32(r->raddr));
+ if(r->rev >= 2)
+ if(checksum(r, 36) == 0)
+ maptable(get64(r->xaddr));
+ addarchfile("acpitbls", 0444, readtbls, nil);
+}
diff --git a/sys/src/9/pc/pccpuf b/sys/src/9/pc/pccpuf
index 44c765b73..4625e2dc2 100644
--- a/sys/src/9/pc/pccpuf
+++ b/sys/src/9/pc/pccpuf
@@ -41,6 +41,7 @@ link
devpccard
devi82365
cputemp
+ acpi
apm apmjump
ether2000 ether8390
ether2114x pci
diff --git a/sys/src/9/pc/pcf b/sys/src/9/pc/pcf
index 6bc01ae6b..8b2f54aae 100644
--- a/sys/src/9/pc/pcf
+++ b/sys/src/9/pc/pcf
@@ -42,6 +42,7 @@ link
devpccard
devi82365
cputemp
+ acpi
apm apmjump
ether2000 ether8390
ether2114x pci