summaryrefslogtreecommitdiff
path: root/sys/src/9/pc/memory.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-07-22 21:00:20 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2018-07-22 21:00:20 +0200
commit0431ea242d8856c5a780ab3a01252f3909349a49 (patch)
tree9a2d0f92d001ddcd16a89e370353885c89ef182d /sys/src/9/pc/memory.c
parentf4b9f0304dee1e94dbee35e30765f8a7349794ba (diff)
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.
Diffstat (limited to 'sys/src/9/pc/memory.c')
-rw-r--r--sys/src/9/pc/memory.c84
1 files changed, 69 insertions, 15 deletions
diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c
index 25f979437..fb14d017e 100644
--- a/sys/src/9/pc/memory.c
+++ b/sys/src/9/pc/memory.c
@@ -21,8 +21,9 @@ enum {
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 @@ static RMap rmapumbrw = {
&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 @@ memdebug(void)
mapprint(&rmapumb);
mapprint(&rmapumbrw);
mapprint(&rmapupa);
+ mapprint(&rmapacpi);
}
static void
@@ -327,16 +336,20 @@ checksum(void *v, int n)
}
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 @@ convmemsize(void)
}
void*
-sigsearch(char* signature)
+sigsearch(char* signature, int size)
{
uintptr p;
uchar *bda;
@@ -376,18 +389,44 @@ sigsearch(char* signature)
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
@@ -683,6 +722,10 @@ map(ulong base, ulong len, int type)
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 @@ e820scan(void)
*/
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;