kernel: add debug driver for dumping acpi tables

This commit is contained in:
cinap_lenrek 2012-05-19 01:58:40 +02:00
parent 9891d13887
commit b44038fec0
3 changed files with 221 additions and 0 deletions

219
sys/src/9/pc/acpi.c Normal file
View file

@ -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);
}

View file

@ -41,6 +41,7 @@ link
devpccard
devi82365
cputemp
acpi
apm apmjump
ether2000 ether8390
ether2114x pci

View file

@ -42,6 +42,7 @@ link
devpccard
devi82365
cputemp
acpi
apm apmjump
ether2000 ether8390
ether2114x pci