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);
|
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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue