git: 9front

Download patch

ref: e98911d5f2a9d7df40519fc363017f86515d8a17
parent: 5394183be76afba9d039055abd605df8e58daeb5
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri Aug 24 11:36:56 EDT 2012

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.

--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -79,55 +79,7 @@
 	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){
 	int i;
@@ -538,7 +490,9 @@
 
 	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)
--- a/sys/src/9/pc/archmp.c
+++ b/sys/src/9/pc/archmp.c
@@ -354,51 +354,6 @@
 	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 @@
 {
 	char *cp;
 	_MP_ *_mp_;
-	uchar *p, sum;
-	ulong length;
 
 	if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
 		return 1;
@@ -431,21 +384,12 @@
 	 * 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;
 	}
--- 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 @@
 	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 @@
 	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));
 
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -9,6 +9,7 @@
 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	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);
--- a/sys/src/9/pc/memory.c
+++ b/sys/src/9/pc/memory.c
@@ -313,6 +313,66 @@
 	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)
 {
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -739,19 +739,17 @@
 	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 = sigsearch("$PIR")) == 0)
+		return;
 
-	if(p >= (uchar *)KADDR(0xfffff))
+	r = (Router*)p;
+	size = (r->size[1] << 8)|r->size[0];
+	if(size < sizeof(Router) || checksum(r, size))
 		return;
 
-	r = (Router *)p;
+	if(0) print("PCI interrupt routing table version %d.%d at %p\n",
+		r->version[0], r->version[1], r);
 
-	// print("PCI interrupt routing table version %d.%d at %.6uX\n",
-	//	r->version[0], r->version[1], (ulong)r & 0xfffff);
-
 	tbdf = (BusPCI << 24)|(r->bus << 16)|(r->devfn << 8);
 	sbpci = pcimatchtbdf(tbdf);
 	if(sbpci == nil) {
@@ -772,8 +770,6 @@
 		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);
--