From b44038fec0e84eece7c0143c59f3e991c55a6147 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 19 May 2012 01:58:40 +0200 Subject: [PATCH] kernel: add debug driver for dumping acpi tables --- sys/src/9/pc/acpi.c | 219 ++++++++++++++++++++++++++++++++++++++++++++ sys/src/9/pc/pccpuf | 1 + sys/src/9/pc/pcf | 1 + 3 files changed, 221 insertions(+) create mode 100644 sys/src/9/pc/acpi.c 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; isig, 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