summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-08-24 15:36:56 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-08-24 15:36:56 +0200
commitd436b2117e5c054c9977f80cae9c2302ed50a5a6 (patch)
treeea29213acd0c5b67ccefdd3348cdca9125227a40
parent86f323290c9f99b72e359ff2c37eed528f5b3976 (diff)
add unified sigsearch() function to look for bios data structures
replace the various functions that searched for bios data structures by a single sigsearch() one in pc/memory.c that will probe the various bios data areas. also, a new checksum() function was added that is to be used to validate the structures found.
-rw-r--r--sys/src/9/pc/archacpi.c52
-rw-r--r--sys/src/9/pc/archmp.c62
-rw-r--r--sys/src/9/pc/bios32.c36
-rw-r--r--sys/src/9/pc/fns.h2
-rw-r--r--sys/src/9/pc/memory.c60
-rw-r--r--sys/src/9/pc/pci.c18
6 files changed, 77 insertions, 153 deletions
diff --git a/sys/src/9/pc/archacpi.c b/sys/src/9/pc/archacpi.c
index bff356d25..f1c94e607 100644
--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -79,54 +79,6 @@ tbldlen(Tbl *t){
return get32(t->len) - sizeof(Tbl);
}
-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 Tbl*
findtable(void *sig){
@@ -538,7 +490,9 @@ identify(void)
if((cp = getconf("*acpi")) == nil)
return 1;
- if((rsd = rsdsearch("RSD PTR ")) == nil)
+ if((rsd = sigsearch("RSD PTR ")) == nil)
+ return 1;
+ if(checksum(rsd, 20) && checksum(rsd, 36))
return 1;
addarchfile("acpitbls", 0444, readtbls, nil);
if(strcmp(cp, "0") == 0)
diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c
index 7d72e0462..3247e04f5 100644
--- a/sys/src/9/pc/archmp.c
+++ b/sys/src/9/pc/archmp.c
@@ -354,51 +354,6 @@ pcmpinit(void)
mpinit();
}
-static _MP_*
-mpscan(uchar *addr, int len)
-{
- uchar *e, *p, sum;
- int i;
-
- e = addr+len;
- for(p = addr; p < e; p += sizeof(_MP_)){
- if(memcmp(p, "_MP_", 4))
- continue;
- sum = 0;
- for(i = 0; i < sizeof(_MP_); i++)
- sum += p[i];
- if(sum == 0)
- return (_MP_*)p;
- }
- return 0;
-}
-
-static _MP_*
-mpsearch(void)
-{
- uchar *bda;
- ulong p;
- _MP_ *mp;
-
- /*
- * Search for the MP Floating Pointer Structure:
- * 1) in the first KB of the EBDA;
- * 2) in the last KB of system base memory;
- * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
- */
- bda = KADDR(0x400);
- if((p = (bda[0x0F]<<8)|bda[0x0E])){
- if(mp = mpscan(KADDR(p<<4), 1024))
- return mp;
- }
- else{
- p = ((bda[0x14]<<8)|bda[0x13])*1024;
- if(mp = mpscan(KADDR(p-1024), 1024))
- return mp;
- }
- return mpscan(KADDR(0xF0000), 0x10000);
-}
-
static int identify(void);
PCArch archmp = {
@@ -418,8 +373,6 @@ identify(void)
{
char *cp;
_MP_ *_mp_;
- uchar *p, sum;
- ulong length;
if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
return 1;
@@ -431,21 +384,12 @@ identify(void)
* if correct, check the version.
* To do: check extended table checksum.
*/
- if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0)
+ if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0)
return 1;
pcmp = KADDR(_mp_->physaddr);
- if(memcmp(pcmp, "PCMP", 4)){
- pcmp = nil;
- return 1;
- }
-
- length = pcmp->length;
- sum = 0;
- for(p = (uchar*)pcmp; length; length--)
- sum += *p++;
-
- if(sum || (pcmp->version != 1 && pcmp->version != 4)){
+ if(memcmp(pcmp, "PCMP", 4) || checksum(pcmp, pcmp->length) ||
+ (pcmp->version != 1 && pcmp->version != 4)) {
pcmp = nil;
return 1;
}
diff --git a/sys/src/9/pc/bios32.c b/sys/src/9/pc/bios32.c
index e0858b9ab..e2976abfd 100644
--- a/sys/src/9/pc/bios32.c
+++ b/sys/src/9/pc/bios32.c
@@ -7,7 +7,6 @@
#define VFLAG(...) if(vflag) print(__VA_ARGS__)
-#define BIOSSEG(a) KADDR(((uint)(a))<<4)
#define UPTR2INT(p) ((uintptr)(p))
#define l16get(p) (((p)[1]<<8)|(p)[0])
@@ -48,37 +47,6 @@ bios32ci(BIOS32si* si, BIOS32ci* ci)
return r;
}
-static void*
-rsdchecksum(void* addr, int length)
-{
- u8int *p, sum;
-
- sum = 0;
- for(p = addr; length-- > 0; p++)
- sum += *p;
- if(sum == 0)
- return addr;
-
- return nil;
-}
-
-static void*
-rsdscan(u8int* addr, int len, char* signature)
-{
- int sl;
- u8int *e, *p;
-
- e = addr+len;
- sl = strlen(signature);
- for(p = addr; p+sl < e; p += 16){
- if(memcmp(p, signature, sl))
- continue;
- return p;
- }
-
- return nil;
-}
-
static int
bios32locate(void)
{
@@ -86,9 +54,9 @@ bios32locate(void)
BIOS32sdh *sdh;
VFLAG("bios32link\n");
- if((sdh = rsdscan(BIOSSEG(0xE000), 0x20000, "_32_")) == nil)
+ if((sdh = sigsearch("_32_")) == nil)
return -1;
- if(rsdchecksum(sdh, sizeof(BIOS32sdh)) == nil)
+ if(checksum(sdh, sizeof(BIOS32sdh)))
return -1;
VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr));
diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h
index 06ce8f8ef..040c4b066 100644
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -9,6 +9,7 @@ void bios32close(BIOS32si*);
BIOS32si* bios32open(char*);
void bootargs(void*);
ulong cankaddr(ulong);
+int checksum(void *, int);
void clockintr(Ureg*, void*);
int (*cmpswap)(long*, long, long);
int cmpswap486(long*, long, long);
@@ -157,6 +158,7 @@ void rdmsr(int, vlong*);
void realmode(Ureg*);
void screeninit(void);
void (*screenputs)(char*, int);
+void* sigsearch(char*);
void syncclock(void);
void syscallfmt(int syscallno, ulong pc, va_list list);
void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop);
diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c
index 994a104d5..28cf44ed0 100644
--- a/sys/src/9/pc/memory.c
+++ b/sys/src/9/pc/memory.c
@@ -313,6 +313,66 @@ umbscan(void)
umbexclude();
}
+int
+checksum(void *v, int n)
+{
+ uchar *p, s;
+
+ s = 0;
+ p = v;
+ while(n-- > 0)
+ s += *p++;
+ return s;
+}
+
+static void*
+sigscan(uchar* addr, int len, char* signature)
+{
+ int sl;
+ uchar *e, *p;
+
+ e = addr+len;
+ sl = strlen(signature);
+ for(p = addr; p+sl < e; p += 16)
+ if(memcmp(p, signature, sl) == 0)
+ return p;
+ return nil;
+}
+
+void*
+sigsearch(char* signature)
+{
+ uintptr p;
+ uchar *bda;
+ void *r;
+
+ /*
+ * Search for the data structure:
+ * 1) within the first KiB of the Extended BIOS Data Area (EBDA), or
+ * 2) within the last KiB of system base memory if the EBDA segment
+ * is undefined, or
+ * 3) within the BIOS ROM address space between 0xf0000 and 0xfffff
+ * (but will actually check 0xe0000 to 0xfffff).
+ */
+ bda = KADDR(0x400);
+ if(memcmp(KADDR(0xfffd9), "EISA", 4) == 0){
+ if((p = (bda[0x0f]<<8)|bda[0x0e]) != 0){
+ if((r = sigscan(KADDR(p<<4), 1024, signature)) != nil)
+ return r;
+ }
+ }
+
+ if((p = ((bda[0x14]<<8)|bda[0x13])*1024) != 0){
+ if((r = sigscan(KADDR(p-1024), 1024, signature)) != nil)
+ return r;
+ }
+ /* hack for virtualbox: look in KiB below 0xa0000 */
+ if((r = sigscan(KADDR(0xa0000-1024), 1024, signature)) != nil)
+ return r;
+
+ return sigscan(KADDR(0xe0000), 0x20000, signature);
+}
+
static void
lowraminit(void)
{
diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c
index a2915da1d..e27f04ddf 100644
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -739,18 +739,16 @@ pcirouting(void)
Pcidev *sbpci, *pci;
uchar *p, pin, irq, link, *map;
- /* Search for PCI interrupt routing table in BIOS */
- for(p = (uchar *)KADDR(0xf0000); p < (uchar *)KADDR(0xfffff); p += 16)
- if(p[0] == '$' && p[1] == 'P' && p[2] == 'I' && p[3] == 'R')
- break;
-
- if(p >= (uchar *)KADDR(0xfffff))
+ if((p = sigsearch("$PIR")) == 0)
return;
- r = (Router *)p;
+ r = (Router*)p;
+ size = (r->size[1] << 8)|r->size[0];
+ if(size < sizeof(Router) || checksum(r, size))
+ return;
- // print("PCI interrupt routing table version %d.%d at %.6uX\n",
- // r->version[0], r->version[1], (ulong)r & 0xfffff);
+ if(0) print("PCI interrupt routing table version %d.%d at %p\n",
+ r->version[0], r->version[1], r);
tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8);
sbpci = pcimatchtbdf(tbdf);
@@ -772,8 +770,6 @@ pcirouting(void)
return;
pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0];
-
- size = (r->size[1] << 8)|r->size[0];
for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) {
if (0) {
print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot);