summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-05-14 19:20:16 +0000
committercinap_lenrek <cinap_lenrek@localhost>2011-05-14 19:20:16 +0000
commit0ad5929695507eb80f18e177f29f5c51697bcc23 (patch)
tree9fa917c4e3e2cb9b5e06702c75b278be6b211795 /sys/src
parente0c8b9955de9fab16f65ad0471a696a2e8b2fe81 (diff)
9boot: add e820 scan to bootloader
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/9/pc/memory.c60
-rw-r--r--sys/src/boot/pc/apm.s6
-rw-r--r--sys/src/boot/pc/e820.s20
-rw-r--r--sys/src/boot/pc/fns.h2
-rw-r--r--sys/src/boot/pc/mkfile2
-rw-r--r--sys/src/boot/pc/sub.c71
6 files changed, 133 insertions, 28 deletions
diff --git a/sys/src/9/pc/memory.c b/sys/src/9/pc/memory.c
index edf52623e..33121d647 100644
--- a/sys/src/9/pc/memory.c
+++ b/sys/src/9/pc/memory.c
@@ -673,35 +673,51 @@ e820scan(void)
ulong cont, base, len;
uvlong last;
Emap *e;
+ char *s;
- if(getconf("*norealmode") || getconf("*noe820scan"))
- return -1;
-
- cont = 0;
- for(i=0; i<nelem(emap); i++){
- memset(&u, 0, sizeof u);
- u.ax = 0xE820;
- u.bx = cont;
- u.cx = 20;
- u.dx = SMAP;
- u.es = (PADDR(RMBUF)>>4)&0xF000;
- u.di = PADDR(RMBUF)&0xFFFF;
- u.trap = 0x15;
- realmode(&u);
- cont = u.bx;
- if((u.flags&Carry) || u.ax != SMAP || u.cx != 20)
- break;
- e = &emap[nemap++];
- *e = *(Emap*)RMBUF;
- if(u.bx == 0)
- break;
+ if((s = getconf("e820")) != nil){
+ for(nemap = 0; nemap < nelem(emap); nemap++){
+ if(*s == 0)
+ break;
+ e = emap + nemap;
+ e->base = strtoull(s, &s, 16);
+ if(*s != ' ')
+ break;
+ e->len = strtoull(s, &s, 16) - e->base;
+ if(*s != ' ' && *s != 0 || e->len >= 1ull<<32 || e->len == 0)
+ break;
+ e->type = Ememory;
+ }
+ }else{
+ if(getconf("*norealmode") || getconf("*noe820scan"))
+ return -1;
+ cont = 0;
+ for(i=0; i<nelem(emap); i++){
+ memset(&u, 0, sizeof u);
+ u.ax = 0xE820;
+ u.bx = cont;
+ u.cx = 20;
+ u.dx = SMAP;
+ u.es = (PADDR(RMBUF)>>4)&0xF000;
+ u.di = PADDR(RMBUF)&0xFFFF;
+ u.trap = 0x15;
+ realmode(&u);
+ cont = u.bx;
+ if((u.flags&Carry) || u.ax != SMAP || u.cx != 20)
+ break;
+ e = &emap[nemap++];
+ *e = *(Emap*)RMBUF;
+ if(u.bx == 0)
+ break;
+ }
}
+
if(nemap == 0)
return -1;
qsort(emap, nemap, sizeof emap[0], emapcmp);
- if(getconf("*noe820print") == nil){
+ if(s == nil && getconf("*noe820print") == nil){
for(i=0; i<nemap; i++){
e = &emap[i];
print("E820: %.8llux %.8llux ", e->base, e->base+e->len);
diff --git a/sys/src/boot/pc/apm.s b/sys/src/boot/pc/apm.s
index 0a0d41fd1..b6a9104b1 100644
--- a/sys/src/boot/pc/apm.s
+++ b/sys/src/boot/pc/apm.s
@@ -7,19 +7,19 @@ TEXT apm(SB), $0
PUSHR(rBX)
LWI(0x5300, rAX)
- INT $0x15
+ BIOSCALL(0x15)
POPR(rBX)
JC noapm
PUSHR(rBX)
LWI(0x5304, rAX)
- INT $0x15
+ BIOSCALL(0x15)
POPR(rBX)
CLC
/* connect */
LWI(0x5303, rAX)
- INT $0x15
+ BIOSCALL(0x15)
JC noapm
OPSIZE; PUSHR(rSI)
diff --git a/sys/src/boot/pc/e820.s b/sys/src/boot/pc/e820.s
new file mode 100644
index 000000000..c830a64e6
--- /dev/null
+++ b/sys/src/boot/pc/e820.s
@@ -0,0 +1,20 @@
+#include "x16.h"
+#include "mem.h"
+
+TEXT e820(SB), $0
+ MOVL bx+4(SP), BX
+ MOVL p+8(SP), DI
+
+ MOVL $0xe820, AX
+ MOVL $0x534D4150, DX
+ CALL rmode16(SB)
+ LWI(24, rCX)
+ BIOSCALL(0x15)
+ JC _bad
+ CALL16(pmode32(SB))
+ MOVL BX, AX
+ RET
+_bad:
+ CALL16(pmode32(SB))
+ XORL AX, AX
+ RET
diff --git a/sys/src/boot/pc/fns.h b/sys/src/boot/pc/fns.h
index 5135ac5b2..11176f07f 100644
--- a/sys/src/boot/pc/fns.h
+++ b/sys/src/boot/pc/fns.h
@@ -9,8 +9,6 @@ void start(void *sp);
int getc(void);
int gotc(void);
void putc(int c);
-void a20(void);
-void apm(int id);
void halt(void);
void jump(void *pc);
diff --git a/sys/src/boot/pc/mkfile b/sys/src/boot/pc/mkfile
index 4dd12e913..ff6ce3114 100644
--- a/sys/src/boot/pc/mkfile
+++ b/sys/src/boot/pc/mkfile
@@ -36,7 +36,7 @@ pbs: pbs.$O
$LD -o $target -H3 -T0x0600 -l $prereq
ls -l $target
-9boot&: l%.$O %.$O sub.$O apm.$O a20.$O
+9boot&: l%.$O %.$O sub.$O apm.$O e820.$O a20.$O
$LD -o $target -H3 -T0x7c00 -l $prereq
ls -l $target
diff --git a/sys/src/boot/pc/sub.c b/sys/src/boot/pc/sub.c
index 10e5e7a22..205cace13 100644
--- a/sys/src/boot/pc/sub.c
+++ b/sys/src/boot/pc/sub.c
@@ -235,6 +235,8 @@ addconfx(char *s, int w, ulong v)
*confend = 0;
}
+void apm(int id);
+
static void
apmconf(int id)
{
@@ -263,6 +265,73 @@ apmconf(int id)
*confend++ = '\n';
}
+ulong e820(ulong bx, void *p);
+
+static void
+e820conf(void)
+{
+ struct {
+ uvlong base;
+ uvlong len;
+ ulong typ;
+ ulong ext;
+ } e;
+ uvlong v;
+ ulong bx;
+ char *s;
+
+ memset(&e, 0, sizeof(e));
+ if((bx = e820(0, &e)) == 0)
+ return;
+
+ memmove(confend, "e820=", 5);
+ confend += 5;
+
+ do{
+ s = confend;
+ v = e.base;
+ addconfx("", 8, v>>32);
+ addconfx("", 8, v&0xffffffff);
+ v = e.base + e.len;
+ addconfx(" ", 8, v>>32);
+ addconfx("", 8, v&0xffffffff);
+
+ print(s);
+
+ switch(e.typ){
+ case 1:
+ print(" ram");
+ break;
+ case 2:
+ print(" reserved");
+ break;
+ case 3:
+ print(" acpi reclaim");
+ break;
+ case 4:
+ print(" acpi nvs");
+ break;
+ case 5:
+ print(" bad");
+ break;
+ default:
+ print(" ???");
+ }
+ print(crnl);
+
+ if(e.typ == 1 && (e.ext & 1) == 0)
+ *confend++ = ' ';
+ else
+ confend = s;
+ memset(&e, 0, sizeof(e));
+ } while(bx = e820(bx, &e));
+
+ *confend++ = '\n';
+ *confend = 0;
+}
+
+void a20(void);
+
char*
bootkern(void *f)
{
@@ -270,6 +339,8 @@ bootkern(void *f)
ulong n;
Exec ex;
+ e820conf();
+
a20();
if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
return "bad header";