From d436b2117e5c054c9977f80cae9c2302ed50a5a6 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Fri, 24 Aug 2012 15:36:56 +0200 Subject: [PATCH] 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. --- sys/src/9/pc/archacpi.c | 52 ++-------------------------------- sys/src/9/pc/archmp.c | 62 ++--------------------------------------- sys/src/9/pc/bios32.c | 36 ++---------------------- sys/src/9/pc/fns.h | 2 ++ sys/src/9/pc/memory.c | 60 +++++++++++++++++++++++++++++++++++++++ sys/src/9/pc/pci.c | 18 +++++------- 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);