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;