ref: e0c8b9955de9fab16f65ad0471a696a2e8b2fe81
parent: b4f2bf77b3710306bf1965201d526154c9dbddb7
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Sat May 14 13:06:27 EDT 2011
9boot: add APM support
--- /dev/null
+++ b/sys/src/boot/pc/apm.s
@@ -1,0 +1,51 @@
+#include "x16.h"
+#include "mem.h"
+
+TEXT apm(SB), $0
+ MOVL id+4(SP), BX
+ CALL rmode16(SB)
+
+ PUSHR(rBX)
+ LWI(0x5300, rAX)
+ INT $0x15
+ POPR(rBX)
+ JC noapm
+
+ PUSHR(rBX)
+ LWI(0x5304, rAX)
+ INT $0x15
+ POPR(rBX)
+ CLC
+
+ /* connect */
+ LWI(0x5303, rAX)
+ INT $0x15
+ JC noapm
+
+ OPSIZE; PUSHR(rSI)
+ OPSIZE; PUSHR(rBX)
+ PUSHR(rDI)
+ PUSHR(rDX)
+ PUSHR(rCX)
+ PUSHR(rAX)
+
+ LWI(CONFADDR, rDI)
+
+ /*
+ * write APM data. first four bytes are APM\0.
+ */
+ LWI(0x5041, rAX)
+ STOSW
+
+ LWI(0x004d, rAX)
+ STOSW
+
+ LWI(8, rCX)
+apmmove:
+ POPR(rAX)
+ STOSW
+ LOOP apmmove
+
+noapm:
+ CALL16(pmode32(SB))
+ RET
--- a/sys/src/boot/pc/fns.h
+++ b/sys/src/boot/pc/fns.h
@@ -10,6 +10,7 @@
int gotc(void);
void putc(int c);
void a20(void);
+void apm(int id);
void halt(void);
void jump(void *pc);
--- a/sys/src/boot/pc/mem.h
+++ b/sys/src/boot/pc/mem.h
@@ -16,8 +16,8 @@
/*
* Fundamental addresses
*/
-#define CONFADDR 0x80001200 /* info passed from boot loader */
-#define BIOSXCHG 0x80006000 /* To exchange data with the BIOS */
+#define CONFADDR 0x1200 /* info passed from boot loader */
+#define BIOSXCHG 0x6000 /* To exchange data with the BIOS */
#define SELGDT (0<<3) /* selector is in gdt */
#define SELLDT (1<<3) /* selector is in ldt */
--- a/sys/src/boot/pc/mkfile
+++ b/sys/src/boot/pc/mkfile
@@ -36,7 +36,7 @@
$LD -o $target -H3 -T0x0600 -l $prereq
ls -l $target
-9boot&: l%.$O %.$O sub.$O a20.$O
+9boot&: l%.$O %.$O sub.$O apm.$O a20.$O
$LD -o $target -H3 -T0x7c00 -l $prereq
ls -l $target
--- a/sys/src/boot/pc/sub.c
+++ b/sys/src/boot/pc/sub.c
@@ -129,18 +129,26 @@
return p - buf;
}
+#define BOOTLINE ((char*)CONFADDR)
+#define BOOTLINELEN 64
+#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
+#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
+
+char *confend;
+
+static void apmconf(int);
+
char*
configure(void *f, char *path)
{
- char line[64], *p, *kern;
+ char line[64], *kern, *p;
int inblock, n;
-
Clear:
kern = 0;
inblock = 0;
- p = (char*)(CONFADDR & ~0xF0000000UL);
- memset(p, 0, 0xE00);
- p += 64;
+
+ confend = (char*)BOOTARGS;
+ memset(confend, 0, BOOTARGSLEN);
Loop:
while((n = readline(f, line)) > 0){
if(*line == 0 || strchr("#;=", *line))
@@ -149,21 +157,25 @@
inblock = memcmp("[common]", line, 8);
continue;
}
- if(memcmp("clear", line, 6) == 0){
+ if(!memcmp("clear", line, 6)){
print("ok\r\n");
goto Clear;
}
- if(memcmp("boot", line, 5) == 0)
+ if(!memcmp("boot", line, 5))
break;
if(inblock || !strrchr(line, '='))
continue;
- print(line); print(crnl);
- if(memcmp("bootfile=", line, 9) == 0)
+ if(!memcmp("bootfile=", line, 9))
memmove(kern = path, line+9, 1 + n-9);
- memmove(p, line, n); p += n;
- *p++ = '\n';
+ if(!memcmp("apm", line, 3) && line[4]=='='){
+ apmconf('0' - line[3]);
+ continue;
+ }
+ memmove(confend, line, n); confend += n;
+ *confend++ = '\n';
+ print(line); print(crnl);
}
- *p = 0;
+ *confend = 0;
if(f){
close(f);
f = 0;
@@ -177,6 +189,7 @@
goto Loop;
if(p = strrchr(kern, '!'))
kern = p+1;
+
return kern;
}
@@ -199,6 +212,57 @@
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
+static void
+hexfmt(char *s, int i, ulong a)
+{
+ s += i;
+ while(i > 0){
+ *--s = hex[a&15];
+ a >>= 4;
+ i--;
+ }
+}
+
+static void
+addconfx(char *s, int w, ulong v)
+{
+ int n;
+
+ n = strlen(s);
+ memmove(confend, s, n);
+ hexfmt(confend+n, w, v);
+ confend += n+w;
+ *confend = 0;
+}
+
+static void
+apmconf(int id)
+{
+ uchar *a;
+ char *s;
+
+ a = (uchar*)CONFADDR;
+ memset(a, 0, 20);
+
+ apm(id);
+ if(memcmp(a, "APM", 4))
+ return;
+
+ s = confend;
+
+ addconfx("apm", 1, id);
+ addconfx("=ax=", 4, *((ushort*)(a+4)));
+ addconfx(" ebx=", 8, *((ulong*)(a+12)));
+ addconfx(" cx=", 4, *((ushort*)(a+6)));
+ addconfx(" dx=", 4, *((ushort*)(a+8)));
+ addconfx(" di=", 4, *((ushort*)(a+10)));
+ addconfx(" esi=", 8, *((ulong*)(a+16)));
+
+ print(s); print(crnl);
+
+ *confend++ = '\n';
+}
+
char*
bootkern(void *f)
{
@@ -223,6 +287,7 @@
goto Error;
close(f);
unload();
+ memset(BOOTLINE, 0, BOOTLINELEN);
jump(e);
Error:
return "i/o error";