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:
parent
86f323290c
commit
d436b2117e
6 changed files with 77 additions and 153 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue