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.
This commit is contained in:
cinap_lenrek 2012-08-24 15:36:56 +02:00
parent 86f323290c
commit d436b2117e
6 changed files with 77 additions and 153 deletions

View file

@ -79,54 +79,6 @@ tbldlen(Tbl *t){
return get32(t->len) - sizeof(Tbl); 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* static Tbl*
findtable(void *sig){ findtable(void *sig){
@ -538,7 +490,9 @@ identify(void)
if((cp = getconf("*acpi")) == nil) if((cp = getconf("*acpi")) == nil)
return 1; 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; return 1;
addarchfile("acpitbls", 0444, readtbls, nil); addarchfile("acpitbls", 0444, readtbls, nil);
if(strcmp(cp, "0") == 0) if(strcmp(cp, "0") == 0)

View file

@ -354,51 +354,6 @@ pcmpinit(void)
mpinit(); 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); static int identify(void);
PCArch archmp = { PCArch archmp = {
@ -418,8 +373,6 @@ identify(void)
{ {
char *cp; char *cp;
_MP_ *_mp_; _MP_ *_mp_;
uchar *p, sum;
ulong length;
if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0) if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
return 1; return 1;
@ -431,21 +384,12 @@ identify(void)
* if correct, check the version. * if correct, check the version.
* To do: check extended table checksum. * To do: check extended table checksum.
*/ */
if((_mp_ = mpsearch()) == 0 || _mp_->physaddr == 0) if((_mp_ = sigsearch("_MP_")) == 0 || _mp_->physaddr == 0)
return 1; return 1;
pcmp = KADDR(_mp_->physaddr); pcmp = KADDR(_mp_->physaddr);
if(memcmp(pcmp, "PCMP", 4)){ if(memcmp(pcmp, "PCMP", 4) || checksum(pcmp, pcmp->length) ||
pcmp = nil; (pcmp->version != 1 && pcmp->version != 4)) {
return 1;
}
length = pcmp->length;
sum = 0;
for(p = (uchar*)pcmp; length; length--)
sum += *p++;
if(sum || (pcmp->version != 1 && pcmp->version != 4)){
pcmp = nil; pcmp = nil;
return 1; return 1;
} }

View file

@ -7,7 +7,6 @@
#define VFLAG(...) if(vflag) print(__VA_ARGS__) #define VFLAG(...) if(vflag) print(__VA_ARGS__)
#define BIOSSEG(a) KADDR(((uint)(a))<<4)
#define UPTR2INT(p) ((uintptr)(p)) #define UPTR2INT(p) ((uintptr)(p))
#define l16get(p) (((p)[1]<<8)|(p)[0]) #define l16get(p) (((p)[1]<<8)|(p)[0])
@ -48,37 +47,6 @@ bios32ci(BIOS32si* si, BIOS32ci* ci)
return r; 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 static int
bios32locate(void) bios32locate(void)
{ {
@ -86,9 +54,9 @@ bios32locate(void)
BIOS32sdh *sdh; BIOS32sdh *sdh;
VFLAG("bios32link\n"); VFLAG("bios32link\n");
if((sdh = rsdscan(BIOSSEG(0xE000), 0x20000, "_32_")) == nil) if((sdh = sigsearch("_32_")) == nil)
return -1; return -1;
if(rsdchecksum(sdh, sizeof(BIOS32sdh)) == nil) if(checksum(sdh, sizeof(BIOS32sdh)))
return -1; return -1;
VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr)); VFLAG("sdh @ %#p, entry %#ux\n", sdh, l32get(sdh->physaddr));

View file

@ -9,6 +9,7 @@ void bios32close(BIOS32si*);
BIOS32si* bios32open(char*); BIOS32si* bios32open(char*);
void bootargs(void*); void bootargs(void*);
ulong cankaddr(ulong); ulong cankaddr(ulong);
int checksum(void *, int);
void clockintr(Ureg*, void*); void clockintr(Ureg*, void*);
int (*cmpswap)(long*, long, long); int (*cmpswap)(long*, long, long);
int cmpswap486(long*, long, long); int cmpswap486(long*, long, long);
@ -157,6 +158,7 @@ void rdmsr(int, vlong*);
void realmode(Ureg*); void realmode(Ureg*);
void screeninit(void); void screeninit(void);
void (*screenputs)(char*, int); void (*screenputs)(char*, int);
void* sigsearch(char*);
void syncclock(void); void syncclock(void);
void syscallfmt(int syscallno, ulong pc, va_list list); void syscallfmt(int syscallno, ulong pc, va_list list);
void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop); void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop);

View file

@ -313,6 +313,66 @@ umbscan(void)
umbexclude(); 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 static void
lowraminit(void) lowraminit(void)
{ {

View file

@ -739,18 +739,16 @@ pcirouting(void)
Pcidev *sbpci, *pci; Pcidev *sbpci, *pci;
uchar *p, pin, irq, link, *map; uchar *p, pin, irq, link, *map;
/* Search for PCI interrupt routing table in BIOS */ if((p = sigsearch("$PIR")) == 0)
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))
return; 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", if(0) print("PCI interrupt routing table version %d.%d at %p\n",
// r->version[0], r->version[1], (ulong)r & 0xfffff); r->version[0], r->version[1], r);
tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8); tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8);
sbpci = pcimatchtbdf(tbdf); sbpci = pcimatchtbdf(tbdf);
@ -772,8 +770,6 @@ pcirouting(void)
return; return;
pciirqs = (r->pciirqs[1] << 8)|r->pciirqs[0]; 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++) { for(e = (Slot *)&r[1]; (uchar *)e < p + size; e++) {
if (0) { if (0) {
print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot); print("%.2uX/%.2uX %.2uX: ", e->bus, e->dev, e->slot);