shithub: riscv

Download patch

ref: 0431ea242d8856c5a780ab3a01252f3909349a49
parent: f4b9f0304dee1e94dbee35e30765f8a7349794ba
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jul 22 17:00:20 EDT 2018

pc, pc64: look for "RSD PTR " in ACPI reserved memory region from e820 map

nobody passes us the "RSD PTR " address when doing multiboot/kexec
on UEFI systems. so we search for it manually in the ACPI reserved
area as indicated in the e820 memory map.

--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -788,7 +788,7 @@
 		return 1;
 	pa = (uintptr)strtoull(cp, nil, 16);
 	if(pa <= 1)
-		rsd = sigsearch("RSD PTR ");
+		rsd = rsdsearch();
 	else if(pa < MemMin)
 		rsd = KADDR(pa);
 	else
--- a/sys/src/9/pc/archmp.c
+++ b/sys/src/9/pc/archmp.c
@@ -395,7 +395,7 @@
 	 * if correct, check the version.
 	 * To do: check extended table checksum.
 	 */
-	if((_mp_ = sigsearch("_MP_")) == nil || checksum(_mp_, _MP_sz) != 0 || _mp_->physaddr == 0)
+	if((_mp_ = sigsearch("_MP_", _MP_sz)) == nil || _mp_->physaddr == 0)
 		return 1;
 
 	len = PCMPsz;
--- a/sys/src/9/pc/bios32.c
+++ b/sys/src/9/pc/bios32.c
@@ -54,9 +54,7 @@
 	BIOS32sdh *sdh;
 
 	VFLAG("bios32link\n");
-	if((sdh = sigsearch("_32_")) == nil)
-		return -1;
-	if(checksum(sdh, sizeof(BIOS32sdh)))
+	if((sdh = sigsearch("_32_", sizeof(BIOS32sdh))) == nil)
 		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
@@ -171,10 +171,11 @@
 void*	rampage(void);
 int	rdmsr(int, vlong*);
 void	realmode(Ureg*);
+void*	rsdsearch(void);
 void	screeninit(void);
 void	(*screenputs)(char*, int);
 void	setconfenv(void);
-void*	sigsearch(char*);
+void*	sigsearch(char*, int);
 void	syncclock(void);
 void*	tmpmap(Page*);
 void	tmpunmap(void*);
--- a/sys/src/9/pc/memory.c
+++ b/sys/src/9/pc/memory.c
@@ -21,8 +21,9 @@
 	MemUPA		= 0,		/* unbacked physical address */
 	MemRAM		= 1,		/* physical memory */
 	MemUMB		= 2,		/* upper memory block (<16MB) */
-	MemReserved	= 3,
-	NMemType	= 4,
+	MemACPI		= 3,		/* ACPI tables */
+	MemReserved	= 4,
+	NMemType	= 5,
 
 	KB		= 1024,
 
@@ -75,6 +76,13 @@
 	&mapumbrw[nelem(mapumbrw)-1],
 };
 
+static Map mapacpi[16];
+static RMap rmapacpi = {
+	"ACPI tables",
+	mapacpi,
+	&mapacpi[nelem(mapacpi)-1],
+};
+
 void
 mapprint(RMap *rmap)
 {
@@ -101,6 +109,7 @@
 	mapprint(&rmapumb);
 	mapprint(&rmapumbrw);
 	mapprint(&rmapupa);
+	mapprint(&rmapacpi);
 }
 
 static void
@@ -327,16 +336,20 @@
 }
 
 static void*
-sigscan(uchar* addr, int len, char* signature)
+sigscan(uchar *addr, int len, char *sig, int size, int step)
 {
-	int sl;
 	uchar *e, *p;
+	int sl;
 
-	e = addr+len;
-	sl = strlen(signature);
-	for(p = addr; p+sl < e; p += 16)
-		if(memcmp(p, signature, sl) == 0)
-			return p;
+	sl = strlen(sig);
+	e = addr+len-(size > sl ? size : sl);
+	for(p = addr; p <= e; p += step){
+		if(memcmp(p, sig, sl) != 0)
+			continue;
+		if(size && checksum(p, size) != 0)
+			continue;
+		return p;
+	}
 	return nil;
 }
 
@@ -359,7 +372,7 @@
 }
 
 void*
-sigsearch(char* signature)
+sigsearch(char* signature, int size)
 {
 	uintptr p;
 	uchar *bda;
@@ -376,20 +389,46 @@
 	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)
+			if((r = sigscan(KADDR(p<<4), 1024, signature, size, 16)) != nil)
 				return r;
 		}
 	}
-	if((r = sigscan(KADDR(convmemsize()), 1024, signature)) != nil)
+	if((r = sigscan(KADDR(convmemsize()), 1024, signature, size, 16)) != nil)
 		return r;
 
 	/* hack for virtualbox: look in KiB below 0xa0000 */
-	if((r = sigscan(KADDR(0xa0000-1024), 1024, signature)) != nil)
+	if((r = sigscan(KADDR(0xa0000-1024), 1024, signature, size, 16)) != nil)
 		return r;
 
-	return sigscan(KADDR(0xe0000), 0x20000, signature);
+	return sigscan(KADDR(0xe0000), 0x20000, signature, size, 16);
 }
 
+void*
+rsdsearch(void)
+{
+	static char signature[] = "RSD PTR ";
+	uchar *v, *p;
+	Map *m;
+
+	if((p = sigsearch(signature, 36)) != nil)
+		return p;
+	if((p = sigsearch(signature, 20)) != nil)
+		return p;
+	for(m = rmapacpi.map; m < rmapacpi.mapend && m->size; m++){
+		if(m->size > 0x7FFFFFFF)
+			continue;
+		if((v = vmap(m->addr, m->size)) != nil){
+			p = sigscan(v, m->size, signature, 36, 4);
+			if(p == nil)
+				p = sigscan(v, m->size, signature, 20, 4);
+			vunmap(v, m->size);
+			if(p != nil)
+				return vmap(m->addr + (p - v), 64);
+		}
+	}
+	return nil;
+}
+
 static void
 lowraminit(void)
 {
@@ -683,6 +722,10 @@
 		mapfree(&rmapupa, base, len);
 		flags = 0;
 		break;
+	case MemACPI:
+		mapfree(&rmapacpi, base, len);
+		flags = 0;
+		break;
 	default:
 	case MemReserved:
 		flags = 0;
@@ -774,7 +817,18 @@
 		 */
 		if(last < base)
 			map(last, base-last, MemUPA);
-		map(base, len, (e->type == 1) ? MemRAM : MemReserved);
+
+		switch(e->type){
+		case 1:
+			map(base, len, MemRAM);
+			break;
+		case 3:
+			map(base, len, MemACPI);
+			break;
+		default:
+			map(base, len, MemReserved);
+		}
+
 		last = base + len;
 		if(last == 0)
 			break;
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -748,7 +748,7 @@
 	Pcidev *sbpci, *pci;
 	uchar *p, pin, irq, link, *map;
 
-	if((p = sigsearch("$PIR")) == nil)
+	if((p = sigsearch("$PIR", 0)) == nil)
 		return;
 
 	r = (Router*)p;
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -170,10 +170,11 @@
 void*	rampage(void);
 int	rdmsr(int, vlong*);
 void	realmode(Ureg*);
+void*	rsdsearch(void);
 void	screeninit(void);
 void	(*screenputs)(char*, int);
 void	setconfenv(void);
-void*	sigsearch(char*);
+void*	sigsearch(char*, int);
 void	syncclock(void);
 void	syscallentry(void);
 void	touser(void*);
--- a/sys/src/9/pc64/memory.c
+++ b/sys/src/9/pc64/memory.c
@@ -20,8 +20,9 @@
 	MemUPA		= 0,		/* unbacked physical address */
 	MemRAM		= 1,		/* physical memory */
 	MemUMB		= 2,		/* upper memory block (<16MB) */
-	MemReserved	= 3,
-	NMemType	= 4,
+	MemACPI		= 3,		/* ACPI tables */
+	MemReserved	= 4,
+	NMemType	= 5,
 
 	KB		= 1024,
 };
@@ -72,6 +73,13 @@
 	&mapumbrw[nelem(mapumbrw)-1],
 };
 
+static Map mapacpi[16];
+static RMap rmapacpi = {
+	"ACPI tables",
+	mapacpi,
+	&mapacpi[nelem(mapacpi)-1],
+};
+
 void
 mapprint(RMap *rmap)
 {
@@ -98,6 +106,7 @@
 	mapprint(&rmapumb);
 	mapprint(&rmapumbrw);
 	mapprint(&rmapupa);
+	mapprint(&rmapacpi);
 }
 
 static void
@@ -324,16 +333,20 @@
 }
 
 static void*
-sigscan(uchar* addr, int len, char* signature)
+sigscan(uchar *addr, int len, char *sig, int size, int step)
 {
-	int sl;
 	uchar *e, *p;
+	int sl;
 
-	e = addr+len;
-	sl = strlen(signature);
-	for(p = addr; p+sl < e; p += 16)
-		if(memcmp(p, signature, sl) == 0)
-			return p;
+	sl = strlen(sig);
+	e = addr+len-(size > sl ? size : sl);
+	for(p = addr; p <= e; p += step){
+		if(memcmp(p, sig, sl) != 0)
+			continue;
+		if(size && checksum(p, size) != 0)
+			continue;
+		return p;
+	}
 	return nil;
 }
 
@@ -356,7 +369,7 @@
 }
 
 void*
-sigsearch(char* signature)
+sigsearch(char* signature, int size)
 {
 	uintptr p;
 	uchar *bda;
@@ -373,20 +386,46 @@
 	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)
+			if((r = sigscan(KADDR(p<<4), 1024, signature, size, 16)) != nil)
 				return r;
 		}
 	}
-	if((r = sigscan(KADDR(convmemsize()), 1024, signature)) != nil)
+	if((r = sigscan(KADDR(convmemsize()), 1024, signature, size, 16)) != nil)
 		return r;
 
 	/* hack for virtualbox: look in KiB below 0xa0000 */
-	if((r = sigscan(KADDR(0xa0000-1024), 1024, signature)) != nil)
+	if((r = sigscan(KADDR(0xa0000-1024), 1024, signature, size, 16)) != nil)
 		return r;
 
-	return sigscan(KADDR(0xe0000), 0x20000, signature);
+	return sigscan(KADDR(0xe0000), 0x20000, signature, size, 16);
 }
 
+void*
+rsdsearch(void)
+{
+	static char signature[] = "RSD PTR ";
+	uchar *v, *p;
+	Map *m;
+
+	if((p = sigsearch(signature, 36)) != nil)
+		return p;
+	if((p = sigsearch(signature, 20)) != nil)
+		return p;
+	for(m = rmapacpi.map; m < rmapacpi.mapend && m->size; m++){
+		if(m->size > 0x7FFFFFFF)
+			continue;
+		if((v = vmap(m->addr, m->size)) != nil){
+			p = sigscan(v, m->size, signature, 36, 4);
+			if(p == nil)
+				p = sigscan(v, m->size, signature, 20, 4);
+			vunmap(v, m->size);
+			if(p != nil)
+				return vmap(m->addr + (p - v), 64);
+		}
+	}
+	return nil;
+}
+
 static void
 lowraminit(void)
 {
@@ -514,8 +553,12 @@
 		mapfree(&rmapupa, base, len);
 		flags = 0;
 		break;
-	default:
+	case MemACPI:
+		mapfree(&rmapacpi, base, len);
+		flags = 0;
+		break;
 	case MemReserved:
+	default:
 		flags = 0;
 		break;
 	}
@@ -584,7 +627,16 @@
 		 */
 		if(last < base)
 			map(last, base-last, MemUPA);
-		map(base, len, (e->type == 1) ? MemRAM : MemReserved);
+		switch(e->type){
+		case 1:
+			map(base, len, MemRAM);
+			break;
+		case 3:
+			map(base, len, MemACPI);
+			break;
+		default:
+			map(base, len, MemReserved);
+		}
 		last = base + len;
 		if(last == 0)
 			break;