9boot: add APM support

This commit is contained in:
cinap_lenrek 2011-05-14 17:06:27 +00:00
parent b4f2bf77b3
commit e0c8b9955d
5 changed files with 132 additions and 15 deletions

51
sys/src/boot/pc/apm.s Normal file
View file

@ -0,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

View file

@ -10,6 +10,7 @@ int getc(void);
int gotc(void);
void putc(int c);
void a20(void);
void apm(int id);
void halt(void);
void jump(void *pc);

View file

@ -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 */

View file

@ -36,7 +36,7 @@ pbs: pbs.$O
$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

View file

@ -129,18 +129,26 @@ readline(void *f, char buf[64])
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 @@ Loop:
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 @@ Loop:
goto Loop;
if(p = strrchr(kern, '!'))
kern = p+1;
return kern;
}
@ -199,6 +212,57 @@ beswal(ulong l)
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 @@ bootkern(void *f)
goto Error;
close(f);
unload();
memset(BOOTLINE, 0, BOOTLINELEN);
jump(e);
Error:
return "i/o error";