pc, pc64: support for multiboot framebuffer, common bootargs and multiboot code
This commit is contained in:
parent
ffde0eda46
commit
aab4e32ce0
14 changed files with 400 additions and 405 deletions
189
sys/src/9/pc/bootargs.c
Normal file
189
sys/src/9/pc/bootargs.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
#define MAXCONF 64
|
||||
static char *confname[MAXCONF];
|
||||
static char *confval[MAXCONF];
|
||||
static int nconf;
|
||||
|
||||
/* screen.c */
|
||||
extern char* rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm);
|
||||
|
||||
/* vgavesa.c */
|
||||
extern char* vesabootscreenconf(char*, char*, uchar*);
|
||||
|
||||
static void
|
||||
multibootargs(void)
|
||||
{
|
||||
extern ulong multibootptr;
|
||||
ulong *multiboot;
|
||||
char *cp, *ep;
|
||||
ulong *m, l;
|
||||
|
||||
if(multibootptr == 0)
|
||||
return;
|
||||
|
||||
multiboot = (ulong*)KADDR(multibootptr);
|
||||
|
||||
/* command line */
|
||||
if((multiboot[0] & (1<<2)) != 0)
|
||||
strncpy(BOOTLINE, KADDR(multiboot[4]), BOOTLINELEN-1);
|
||||
|
||||
cp = BOOTARGS;
|
||||
ep = cp + BOOTARGSLEN-1;
|
||||
|
||||
/* memory map */
|
||||
if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){
|
||||
cp = seprint(cp, ep, "*e820=");
|
||||
m = KADDR(multiboot[12]);
|
||||
while(m[0] >= 20 && m[0]+4 <= l){
|
||||
uvlong base, size;
|
||||
m++;
|
||||
base = ((uvlong)m[0] | (uvlong)m[1]<<32);
|
||||
size = ((uvlong)m[2] | (uvlong)m[3]<<32);
|
||||
cp = seprint(cp, ep, "%.1lux %.16llux %.16llux ",
|
||||
m[4] & 0xF, base, base+size);
|
||||
l -= m[-1]+4;
|
||||
m = (ulong*)((uintptr)m + m[-1]);
|
||||
}
|
||||
cp[-1] = '\n';
|
||||
}
|
||||
|
||||
if((multiboot[0] & (1<<12)) != 0 && multiboot[22] != 0){ /* framebuffer */
|
||||
uchar *p = (uchar*)multiboot + 112;
|
||||
int depth = multiboot[27] & 0xFF;
|
||||
char chan[32];
|
||||
|
||||
switch((multiboot[27]>>8) & 0xFF){
|
||||
case 0:
|
||||
snprint(chan, sizeof chan, "m%d", depth);
|
||||
if(0){
|
||||
case 1:
|
||||
rgbmask2chan(chan, depth,
|
||||
(1UL<<p[1])-1 << p[0],
|
||||
(1UL<<p[3])-1 << p[2],
|
||||
(1UL<<p[5])-1 << p[4]);
|
||||
}
|
||||
cp = seprint(cp, ep, "*bootscreen=%dx%dx%d %s %#lux\n",
|
||||
(int)multiboot[24]*8 / depth,
|
||||
(int)multiboot[26],
|
||||
depth,
|
||||
chan,
|
||||
multiboot[22]);
|
||||
}
|
||||
} else
|
||||
if((multiboot[0] & (1<<11)) != 0 && multiboot[19] != 0) /* vbe mode info */
|
||||
cp = vesabootscreenconf(cp, ep, KADDR(multiboot[19]));
|
||||
|
||||
/* plan9.ini passed as the first module */
|
||||
if((multiboot[0] & (1<<3)) != 0 && multiboot[5] > 0){
|
||||
m = KADDR(multiboot[6]);
|
||||
l = m[1] - m[0];
|
||||
m = KADDR(m[0]);
|
||||
if(cp+l > ep)
|
||||
l = ep - cp;
|
||||
memmove(cp, m, l);
|
||||
cp += l;
|
||||
}
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
void
|
||||
bootargsinit(void)
|
||||
{
|
||||
int i, j, n;
|
||||
char *cp, *line[MAXCONF], *p, *q;
|
||||
|
||||
multibootargs();
|
||||
|
||||
/*
|
||||
* parse configuration args from dos file plan9.ini
|
||||
*/
|
||||
cp = BOOTARGS; /* where b.com leaves its config */
|
||||
cp[BOOTARGSLEN-1] = 0;
|
||||
|
||||
/*
|
||||
* Strip out '\r', change '\t' -> ' '.
|
||||
*/
|
||||
p = cp;
|
||||
for(q = cp; *q; q++){
|
||||
if(*q == '\r')
|
||||
continue;
|
||||
if(*q == '\t')
|
||||
*q = ' ';
|
||||
*p++ = *q;
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
n = getfields(cp, line, MAXCONF, 1, "\n");
|
||||
for(i = 0; i < n; i++){
|
||||
if(*line[i] == '#')
|
||||
continue;
|
||||
cp = strchr(line[i], '=');
|
||||
if(cp == nil)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
for(j = 0; j < nconf; j++){
|
||||
if(cistrcmp(confname[j], line[i]) == 0)
|
||||
break;
|
||||
}
|
||||
confname[j] = line[i];
|
||||
confval[j] = cp;
|
||||
if(j == nconf)
|
||||
nconf++;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
getconf(char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nconf; i++)
|
||||
if(cistrcmp(confname[i], name) == 0)
|
||||
return confval[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
setconfenv(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nconf; i++){
|
||||
if(confname[i][0] != '*')
|
||||
ksetenv(confname[i], confval[i], 0);
|
||||
ksetenv(confname[i], confval[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
writeconf(void)
|
||||
{
|
||||
char *p, *q;
|
||||
int n;
|
||||
|
||||
p = getconfenv();
|
||||
if(waserror()) {
|
||||
free(p);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
/* convert to name=value\n format */
|
||||
for(q=p; *q; q++) {
|
||||
q += strlen(q);
|
||||
*q = '=';
|
||||
q += strlen(q);
|
||||
*q = '\n';
|
||||
}
|
||||
n = q - p + 1;
|
||||
if(n >= BOOTARGSLEN)
|
||||
error("kernel configuration too large");
|
||||
memset(BOOTLINE, 0, BOOTLINELEN);
|
||||
memmove(BOOTARGS, p, n);
|
||||
poperror();
|
||||
free(p);
|
||||
}
|
|
@ -8,7 +8,7 @@ int bios32call(BIOS32ci*, u16int[3]);
|
|||
int bios32ci(BIOS32si*, BIOS32ci*);
|
||||
void bios32close(BIOS32si*);
|
||||
BIOS32si* bios32open(char*);
|
||||
void bootargs(void*);
|
||||
void bootargsinit(void);
|
||||
ulong cankaddr(ulong);
|
||||
int checksum(void *, int);
|
||||
void clockintr(Ureg*, void*);
|
||||
|
@ -176,6 +176,7 @@ int rdmsr(int, vlong*);
|
|||
void realmode(Ureg*);
|
||||
void screeninit(void);
|
||||
void (*screenputs)(char*, int);
|
||||
void setconfenv(void);
|
||||
void* sigsearch(char*);
|
||||
void syncclock(void);
|
||||
void* tmpmap(Page*);
|
||||
|
@ -198,6 +199,7 @@ void* vmap(ulong, int);
|
|||
int vmapsync(ulong);
|
||||
void vunmap(void*, int);
|
||||
void wbinvd(void);
|
||||
void writeconf(void);
|
||||
int wrmsr(int, vlong);
|
||||
int xchgw(ushort*, int);
|
||||
void rdrandbuf(void*, ulong);
|
||||
|
|
|
@ -42,8 +42,8 @@ TEXT _startKADDR(SB), $0
|
|||
*/
|
||||
TEXT _multibootheader(SB), $0
|
||||
LONG $0x1BADB002 /* magic */
|
||||
LONG $0x00010003 /* flags */
|
||||
LONG $-(0x1BADB002 + 0x00010003) /* checksum */
|
||||
LONG $0x00010007 /* flags */
|
||||
LONG $-(0x1BADB002 + 0x00010007) /* checksum */
|
||||
LONG $_multibootheader-KZERO(SB) /* header_addr */
|
||||
LONG $_startKADDR-KZERO(SB) /* load_addr */
|
||||
LONG $edata-KZERO(SB) /* load_end_addr */
|
||||
|
@ -52,7 +52,7 @@ TEXT _multibootheader(SB), $0
|
|||
LONG $0 /* mode_type */
|
||||
LONG $0 /* width */
|
||||
LONG $0 /* height */
|
||||
LONG $0 /* depth */
|
||||
LONG $32 /* depth */
|
||||
|
||||
/*
|
||||
* the kernel expects the data segment to be page-aligned
|
||||
|
@ -70,14 +70,13 @@ TEXT _multibootentry(SB), $0
|
|||
INCL CX /* one more for post decrement */
|
||||
STD
|
||||
REP; MOVSB
|
||||
ADDL $KZERO, BX
|
||||
MOVL BX, multiboot-KZERO(SB)
|
||||
MOVL BX, multibootptr-KZERO(SB)
|
||||
MOVL $_startPADDR(SB), AX
|
||||
ANDL $~KZERO, AX
|
||||
JMP* AX
|
||||
|
||||
/* multiboot structure pointer */
|
||||
TEXT multiboot(SB), $0
|
||||
/* multiboot structure pointer (physical address) */
|
||||
TEXT multibootptr(SB), $0
|
||||
LONG $0
|
||||
|
||||
/*
|
||||
|
|
|
@ -11,124 +11,21 @@
|
|||
#include "reboot.h"
|
||||
|
||||
Mach *m;
|
||||
|
||||
/*
|
||||
* Where configuration info is left for the loaded programme.
|
||||
* This will turn into a structure as more is done by the boot loader
|
||||
* (e.g. why parse the .ini file twice?).
|
||||
* There are 3584 bytes available at CONFADDR.
|
||||
*/
|
||||
#define BOOTLINE ((char*)CONFADDR)
|
||||
#define BOOTLINELEN 64
|
||||
#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
|
||||
#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
|
||||
#define MAXCONF 64
|
||||
|
||||
Conf conf;
|
||||
char *confname[MAXCONF];
|
||||
char *confval[MAXCONF];
|
||||
int nconf;
|
||||
|
||||
char *sp; /* user stack of init proc */
|
||||
int delaylink;
|
||||
int idle_spin;
|
||||
|
||||
static void
|
||||
multibootargs(void)
|
||||
{
|
||||
char *cp, *ep;
|
||||
ulong *m, l;
|
||||
|
||||
extern ulong *multiboot;
|
||||
|
||||
if(multiboot == nil)
|
||||
return;
|
||||
|
||||
/* command line */
|
||||
if((multiboot[0] & (1<<2)) != 0)
|
||||
strncpy(BOOTLINE, KADDR(multiboot[4]), BOOTLINELEN-1);
|
||||
|
||||
cp = BOOTARGS;
|
||||
ep = cp + BOOTARGSLEN-1;
|
||||
|
||||
/* memory map */
|
||||
if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){
|
||||
cp = seprint(cp, ep, "*e820=");
|
||||
m = KADDR(multiboot[12]);
|
||||
while(m[0] >= 20 && m[0]+4 <= l){
|
||||
uvlong base, size;
|
||||
m++;
|
||||
base = ((uvlong)m[0] | (uvlong)m[1]<<32);
|
||||
size = ((uvlong)m[2] | (uvlong)m[3]<<32);
|
||||
cp = seprint(cp, ep, "%.1lux %.16llux %.16llux ",
|
||||
m[4] & 0xF, base, base+size);
|
||||
l -= m[-1]+4;
|
||||
m = (ulong*)((ulong)m + m[-1]);
|
||||
}
|
||||
cp[-1] = '\n';
|
||||
}
|
||||
|
||||
/* plan9.ini passed as the first module */
|
||||
if((multiboot[0] & (1<<3)) != 0 && multiboot[5] > 0){
|
||||
m = KADDR(multiboot[6]);
|
||||
l = m[1] - m[0];
|
||||
m = KADDR(m[0]);
|
||||
if(cp+l > ep)
|
||||
l = ep - cp;
|
||||
memmove(cp, m, l);
|
||||
cp += l;
|
||||
}
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
options(void)
|
||||
{
|
||||
long i, n;
|
||||
char *cp, *line[MAXCONF], *p, *q;
|
||||
|
||||
multibootargs();
|
||||
|
||||
/*
|
||||
* parse configuration args from dos file plan9.ini
|
||||
*/
|
||||
cp = BOOTARGS; /* where b.com leaves its config */
|
||||
cp[BOOTARGSLEN-1] = 0;
|
||||
|
||||
/*
|
||||
* Strip out '\r', change '\t' -> ' '.
|
||||
*/
|
||||
p = cp;
|
||||
for(q = cp; *q; q++){
|
||||
if(*q == '\r')
|
||||
continue;
|
||||
if(*q == '\t')
|
||||
*q = ' ';
|
||||
*p++ = *q;
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
n = getfields(cp, line, MAXCONF, 1, "\n");
|
||||
for(i = 0; i < n; i++){
|
||||
if(*line[i] == '#')
|
||||
continue;
|
||||
cp = strchr(line[i], '=');
|
||||
if(cp == nil)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
confname[nconf] = line[i];
|
||||
confval[nconf] = cp;
|
||||
nconf++;
|
||||
}
|
||||
}
|
||||
|
||||
extern void (*i8237alloc)(void);
|
||||
extern void bootscreeninit(void);
|
||||
extern void multibootdebug(void);
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
mach0init();
|
||||
options();
|
||||
bootargsinit();
|
||||
ioinit();
|
||||
i8250console();
|
||||
quotefmtinstall();
|
||||
|
@ -213,7 +110,6 @@ machinit(void)
|
|||
void
|
||||
init0(void)
|
||||
{
|
||||
int i;
|
||||
char buf[2*KNAMELEN];
|
||||
|
||||
up->nerrlab = 0;
|
||||
|
@ -239,17 +135,49 @@ init0(void)
|
|||
ksetenv("service", "cpu", 0);
|
||||
else
|
||||
ksetenv("service", "terminal", 0);
|
||||
for(i = 0; i < nconf; i++){
|
||||
if(confname[i][0] != '*')
|
||||
ksetenv(confname[i], confval[i], 0);
|
||||
ksetenv(confname[i], confval[i], 1);
|
||||
}
|
||||
setconfenv();
|
||||
poperror();
|
||||
}
|
||||
kproc("alarm", alarmkproc, 0);
|
||||
touser(sp);
|
||||
}
|
||||
|
||||
void
|
||||
userbootargs(void *base)
|
||||
{
|
||||
char *argv[8];
|
||||
int i, argc;
|
||||
|
||||
#define UA(ka) ((char*)(ka) + ((uintptr)(USTKTOP - BY2PG) - (uintptr)base))
|
||||
sp = (char*)base + BY2PG - sizeof(Tos);
|
||||
|
||||
/* push boot command line onto the stack */
|
||||
sp -= BOOTLINELEN;
|
||||
sp[BOOTLINELEN-1] = '\0';
|
||||
memmove(sp, BOOTLINE, BOOTLINELEN-1);
|
||||
|
||||
/* parse boot command line */
|
||||
argc = tokenize(sp, argv, nelem(argv));
|
||||
if(argc < 1){
|
||||
strcpy(sp, "boot");
|
||||
argc = 0;
|
||||
argv[argc++] = sp;
|
||||
}
|
||||
|
||||
/* 4 byte word align stack */
|
||||
sp = (char*)((uintptr)sp & ~3);
|
||||
|
||||
/* build argv on stack */
|
||||
sp -= (argc+1)*BY2WD;
|
||||
for(i=0; i<argc; i++)
|
||||
((char**)sp)[i] = UA(argv[i]);
|
||||
((char**)sp)[i] = nil;
|
||||
|
||||
sp = UA(sp);
|
||||
#undef UA
|
||||
sp -= BY2WD;
|
||||
}
|
||||
|
||||
void
|
||||
userinit(void)
|
||||
{
|
||||
|
@ -294,7 +222,7 @@ userinit(void)
|
|||
v = tmpmap(pg);
|
||||
memset(v, 0, BY2PG);
|
||||
segpage(s, pg);
|
||||
bootargs(v);
|
||||
userbootargs(v);
|
||||
tmpunmap(v);
|
||||
|
||||
/*
|
||||
|
@ -314,82 +242,6 @@ userinit(void)
|
|||
ready(p);
|
||||
}
|
||||
|
||||
void
|
||||
bootargs(void *base)
|
||||
{
|
||||
char *argv[8];
|
||||
int i, argc;
|
||||
|
||||
#define UA(ka) ((char*)(ka) + ((uintptr)(USTKTOP - BY2PG) - (uintptr)base))
|
||||
sp = (char*)base + BY2PG - sizeof(Tos);
|
||||
|
||||
/* push boot command line onto the stack */
|
||||
sp -= BOOTLINELEN;
|
||||
sp[BOOTLINELEN-1] = '\0';
|
||||
memmove(sp, BOOTLINE, BOOTLINELEN-1);
|
||||
|
||||
/* parse boot command line */
|
||||
argc = tokenize(sp, argv, nelem(argv));
|
||||
if(argc < 1){
|
||||
strcpy(sp, "boot");
|
||||
argc = 0;
|
||||
argv[argc++] = sp;
|
||||
}
|
||||
|
||||
/* 4 byte word align stack */
|
||||
sp = (char*)((uintptr)sp & ~3);
|
||||
|
||||
/* build argv on stack */
|
||||
sp -= (argc+1)*BY2WD;
|
||||
for(i=0; i<argc; i++)
|
||||
((char**)sp)[i] = UA(argv[i]);
|
||||
((char**)sp)[i] = nil;
|
||||
|
||||
sp = UA(sp);
|
||||
#undef UA
|
||||
sp -= BY2WD;
|
||||
}
|
||||
|
||||
char*
|
||||
getconf(char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nconf; i++)
|
||||
if(cistrcmp(confname[i], name) == 0)
|
||||
return confval[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
writeconf(void)
|
||||
{
|
||||
char *p, *q;
|
||||
int n;
|
||||
|
||||
p = getconfenv();
|
||||
|
||||
if(waserror()) {
|
||||
free(p);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
/* convert to name=value\n format */
|
||||
for(q=p; *q; q++) {
|
||||
q += strlen(q);
|
||||
*q = '=';
|
||||
q += strlen(q);
|
||||
*q = '\n';
|
||||
}
|
||||
n = q - p + 1;
|
||||
if(n >= BOOTARGSLEN)
|
||||
error("kernel configuration too large");
|
||||
memset(BOOTLINE, 0, BOOTLINELEN);
|
||||
memmove(BOOTARGS, p, n);
|
||||
poperror();
|
||||
free(p);
|
||||
}
|
||||
|
||||
void
|
||||
confinit(void)
|
||||
{
|
||||
|
|
|
@ -77,6 +77,17 @@
|
|||
* and that there are 6 of them.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Where configuration info is left for the loaded programme.
|
||||
* This will turn into a structure as more is done by the boot loader
|
||||
* (e.g. why parse the .ini file twice?).
|
||||
* There are 3584 bytes available at CONFADDR.
|
||||
*/
|
||||
#define BOOTLINE ((char*)CONFADDR)
|
||||
#define BOOTLINELEN 64
|
||||
#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
|
||||
#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
|
||||
|
||||
/*
|
||||
* known x86 segments (in GDT) and their selectors
|
||||
*/
|
||||
|
|
|
@ -53,6 +53,7 @@ OBJ=\
|
|||
memory.$O\
|
||||
mmu.$O\
|
||||
trap.$O\
|
||||
bootargs.$O\
|
||||
$CONF.root.$O\
|
||||
$CONF.rootc.$O\
|
||||
$DEVS\
|
||||
|
|
|
@ -587,6 +587,36 @@ bootmapfb(VGAscr *scr, ulong pa, ulong sz)
|
|||
return vgalinearaddr0(scr, pa, sz);
|
||||
}
|
||||
|
||||
char*
|
||||
rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm)
|
||||
{
|
||||
u32int m[4], dm; /* r,g,b,x */
|
||||
char tmp[32];
|
||||
int c, n;
|
||||
|
||||
dm = 1<<depth-1;
|
||||
dm |= dm-1;
|
||||
|
||||
m[0] = rm & dm;
|
||||
m[1] = gm & dm;
|
||||
m[2] = bm & dm;
|
||||
m[3] = (~(m[0] | m[1] | m[2])) & dm;
|
||||
|
||||
buf[0] = 0;
|
||||
Next:
|
||||
for(c=0; c<4; c++){
|
||||
for(n = 0; m[c] & (1<<n); n++)
|
||||
;
|
||||
if(n){
|
||||
m[0] >>= n, m[1] >>= n, m[2] >>= n, m[3] >>= n;
|
||||
snprint(tmp, sizeof tmp, "%c%d%s", "rgbx"[c], n, buf);
|
||||
strcpy(buf, tmp);
|
||||
goto Next;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* called early on boot to attach to framebuffer
|
||||
* setup by bootloader/firmware or plan9.
|
||||
|
@ -682,11 +712,10 @@ bootscreenconf(VGAscr *scr)
|
|||
char conf[100], chan[30];
|
||||
|
||||
conf[0] = '\0';
|
||||
if(scr != nil && scr->paddr != 0)
|
||||
if(scr != nil && scr->paddr != 0 && scr->gscreen != nil)
|
||||
snprint(conf, sizeof(conf), "%dx%dx%d %s %#p %d\n",
|
||||
scr->gscreen->r.max.x, scr->gscreen->r.max.y,
|
||||
scr->gscreen->depth, chantostr(chan, scr->gscreen->chan),
|
||||
scr->paddr, scr->apsize);
|
||||
|
||||
ksetenv("*bootscreen", conf, 1);
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ extern int screensize(int, int, int, ulong);
|
|||
extern int screenaperture(int, int);
|
||||
extern Rectangle physgscreenr; /* actual monitor size */
|
||||
extern void blankscreen(int);
|
||||
extern char* rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm);
|
||||
|
||||
extern void bootscreeninit(void);
|
||||
extern void bootscreenconf(VGAscr*);
|
||||
|
|
|
@ -31,6 +31,17 @@ static Chan *creg, *cmem;
|
|||
#define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8
|
||||
#define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
|
||||
|
||||
typedef struct Vmode Vmode;
|
||||
struct Vmode
|
||||
{
|
||||
char chan[32];
|
||||
int attr; /* flags */
|
||||
int bpl;
|
||||
int dx, dy;
|
||||
int depth;
|
||||
ulong paddr;
|
||||
};
|
||||
|
||||
static uchar*
|
||||
vbesetup(Ureg386 *u, int ax)
|
||||
{
|
||||
|
@ -95,13 +106,37 @@ vbemodeinfo(int mode)
|
|||
return p;
|
||||
}
|
||||
|
||||
static char*
|
||||
vmode(Vmode *m, uchar *p)
|
||||
{
|
||||
m->attr = WORD(p);
|
||||
if(!(m->attr & (1<<4)))
|
||||
return "not in VESA graphics mode";
|
||||
if(!(m->attr & (1<<7)))
|
||||
return "not in linear graphics mode";
|
||||
m->bpl = WORD(p+16);
|
||||
m->dx = WORD(p+18);
|
||||
m->dy = WORD(p+20);
|
||||
m->depth = p[25];
|
||||
m->paddr = LONG(p+40);
|
||||
if(m->depth <= 8)
|
||||
snprint(m->chan, sizeof m->chan, "%c%d",
|
||||
(m->attr & (1<<3)) ? 'm' : 'k', m->depth);
|
||||
else
|
||||
rgbmask2chan(m->chan, m->depth,
|
||||
(1UL<<p[31])-1 << p[32],
|
||||
(1UL<<p[33])-1 << p[34],
|
||||
(1UL<<p[35])-1 << p[36]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
vesalinear(VGAscr *scr, int, int)
|
||||
{
|
||||
int i, mode, size, havesize;
|
||||
ulong paddr;
|
||||
Pcidev *pci;
|
||||
uchar *p;
|
||||
char *err;
|
||||
Vmode m;
|
||||
|
||||
vbecheck();
|
||||
mode = vbegetmode();
|
||||
|
@ -111,14 +146,10 @@ vesalinear(VGAscr *scr, int, int)
|
|||
error("not in linear graphics mode");
|
||||
*/
|
||||
mode &= 0x3FFF;
|
||||
p = vbemodeinfo(mode);
|
||||
if(!(WORD(p+0) & (1<<4)))
|
||||
error("not in VESA graphics mode");
|
||||
if(!(WORD(p+0) & (1<<7)))
|
||||
error("not in linear graphics mode");
|
||||
if((err = vmode(&m, vbemodeinfo(mode))) != nil)
|
||||
error(err);
|
||||
|
||||
paddr = LONG(p+40);
|
||||
size = WORD(p+20)*WORD(p+16);
|
||||
size = m.dy * m.bpl;
|
||||
|
||||
/*
|
||||
* figure out max size of memory so that we have
|
||||
|
@ -136,8 +167,8 @@ vesalinear(VGAscr *scr, int, int)
|
|||
continue;
|
||||
a = pci->mem[i].bar & ~0xF;
|
||||
e = a + pci->mem[i].size;
|
||||
if(paddr >= a && (paddr+size) <= e){
|
||||
size = e - paddr;
|
||||
if(m.paddr >= a && (m.paddr+size) <= e){
|
||||
size = e - m.paddr;
|
||||
havesize = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -151,7 +182,7 @@ vesalinear(VGAscr *scr, int, int)
|
|||
else
|
||||
size = ROUND(size, 1024*1024);
|
||||
|
||||
vgalinearaddr(scr, paddr, size);
|
||||
vgalinearaddr(scr, m.paddr, size);
|
||||
if(scr->apsize)
|
||||
addvgaseg("vesascreen", scr->paddr, scr->apsize);
|
||||
|
||||
|
@ -222,3 +253,19 @@ VGAdev vgavesadev = {
|
|||
vesalinear,
|
||||
vesadrawinit,
|
||||
};
|
||||
|
||||
/*
|
||||
* called from multibootargs() to convert
|
||||
* vbe mode info (passed from bootloader)
|
||||
* to *bootscreen= parameter
|
||||
*/
|
||||
char*
|
||||
vesabootscreenconf(char *s, char *e, uchar *p)
|
||||
{
|
||||
Vmode m;
|
||||
|
||||
if(vmode(&m, p) != nil)
|
||||
return s;
|
||||
return seprint(s, e, "*bootscreen=%dx%dx%d %s %#lux\n",
|
||||
m.bpl * 8 / m.depth, m.dy, m.depth, m.chan, m.paddr);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ int bios32call(BIOS32ci*, u16int[3]);
|
|||
int bios32ci(BIOS32si*, BIOS32ci*);
|
||||
void bios32close(BIOS32si*);
|
||||
BIOS32si* bios32open(char*);
|
||||
void bootargs(void*);
|
||||
void bootargsinit(void);
|
||||
uintptr cankaddr(uintptr);
|
||||
int checksum(void *, int);
|
||||
void clockintr(Ureg*, void*);
|
||||
|
@ -171,6 +171,7 @@ int rdmsr(int, vlong*);
|
|||
void realmode(Ureg*);
|
||||
void screeninit(void);
|
||||
void (*screenputs)(char*, int);
|
||||
void setconfenv(void);
|
||||
void* sigsearch(char*);
|
||||
void syncclock(void);
|
||||
void syscallentry(void);
|
||||
|
@ -191,6 +192,7 @@ void vectortable(void);
|
|||
void* vmap(uintptr, int);
|
||||
void vunmap(void*, int);
|
||||
void wbinvd(void);
|
||||
void writeconf(void);
|
||||
int wrmsr(int, vlong);
|
||||
int xchgw(ushort*, int);
|
||||
void rdrandbuf(void*, ulong);
|
||||
|
|
|
@ -37,8 +37,8 @@ TEXT _protected<>(SB), 1, $-4
|
|||
*/
|
||||
TEXT _multibootheader<>(SB), 1, $-4
|
||||
LONG $0x1BADB002 /* magic */
|
||||
LONG $0x00010003 /* flags */
|
||||
LONG $-(0x1BADB002 + 0x00010003) /* checksum */
|
||||
LONG $0x00010007 /* flags */
|
||||
LONG $-(0x1BADB002 + 0x00010007) /* checksum */
|
||||
LONG $_multibootheader<>-KZERO(SB) /* header_addr */
|
||||
LONG $_protected<>-KZERO(SB) /* load_addr */
|
||||
LONG $edata-KZERO(SB) /* load_end_addr */
|
||||
|
@ -47,7 +47,7 @@ TEXT _multibootheader<>(SB), 1, $-4
|
|||
LONG $0 /* mode_type */
|
||||
LONG $0 /* width */
|
||||
LONG $0 /* height */
|
||||
LONG $0 /* depth */
|
||||
LONG $32 /* depth */
|
||||
|
||||
/*
|
||||
* the kernel expects the data segment to be page-aligned
|
||||
|
|
|
@ -10,22 +10,7 @@
|
|||
#include "pool.h"
|
||||
#include "reboot.h"
|
||||
|
||||
/*
|
||||
* Where configuration info is left for the loaded programme.
|
||||
* This will turn into a structure as more is done by the boot loader
|
||||
* (e.g. why parse the .ini file twice?).
|
||||
* There are 3584 bytes available at CONFADDR.
|
||||
*/
|
||||
#define BOOTLINE ((char*)CONFADDR)
|
||||
#define BOOTLINELEN 64
|
||||
#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
|
||||
#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
|
||||
#define MAXCONF 64
|
||||
|
||||
Conf conf;
|
||||
char *confname[MAXCONF];
|
||||
char *confval[MAXCONF];
|
||||
int nconf;
|
||||
int delaylink;
|
||||
int idle_spin;
|
||||
|
||||
|
@ -34,136 +19,6 @@ char *sp; /* user stack of init proc */
|
|||
extern void (*i8237alloc)(void);
|
||||
extern void bootscreeninit(void);
|
||||
|
||||
static void
|
||||
multibootargs(void)
|
||||
{
|
||||
extern ulong multibootptr;
|
||||
ulong *multiboot;
|
||||
char *cp, *ep;
|
||||
ulong *m, l;
|
||||
|
||||
if(multibootptr == 0)
|
||||
return;
|
||||
|
||||
multiboot = (ulong*)KADDR(multibootptr);
|
||||
/* command line */
|
||||
if((multiboot[0] & (1<<2)) != 0)
|
||||
strncpy(BOOTLINE, KADDR(multiboot[4]), BOOTLINELEN-1);
|
||||
|
||||
cp = BOOTARGS;
|
||||
ep = cp + BOOTARGSLEN-1;
|
||||
|
||||
/* memory map */
|
||||
if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){
|
||||
cp = seprint(cp, ep, "*e820=");
|
||||
m = KADDR(multiboot[12]);
|
||||
while(m[0] >= 20 && m[0]+4 <= l){
|
||||
uvlong base, size;
|
||||
m++;
|
||||
base = ((uvlong)m[0] | (uvlong)m[1]<<32);
|
||||
size = ((uvlong)m[2] | (uvlong)m[3]<<32);
|
||||
cp = seprint(cp, ep, "%.1lux %.16llux %.16llux ",
|
||||
m[4] & 0xF, base, base+size);
|
||||
l -= m[-1]+4;
|
||||
m = (ulong*)((uintptr)m + m[-1]);
|
||||
}
|
||||
cp[-1] = '\n';
|
||||
}
|
||||
|
||||
/* plan9.ini passed as the first module */
|
||||
if((multiboot[0] & (1<<3)) != 0 && multiboot[5] > 0){
|
||||
m = KADDR(multiboot[6]);
|
||||
l = m[1] - m[0];
|
||||
m = KADDR(m[0]);
|
||||
if(cp+l > ep)
|
||||
l = ep - cp;
|
||||
memmove(cp, m, l);
|
||||
cp += l;
|
||||
}
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
options(void)
|
||||
{
|
||||
long i, n;
|
||||
char *cp, *line[MAXCONF], *p, *q;
|
||||
|
||||
multibootargs();
|
||||
|
||||
/*
|
||||
* parse configuration args from dos file plan9.ini
|
||||
*/
|
||||
cp = BOOTARGS; /* where b.com leaves its config */
|
||||
cp[BOOTARGSLEN-1] = 0;
|
||||
|
||||
/*
|
||||
* Strip out '\r', change '\t' -> ' '.
|
||||
*/
|
||||
p = cp;
|
||||
for(q = cp; *q; q++){
|
||||
if(*q == '\r')
|
||||
continue;
|
||||
if(*q == '\t')
|
||||
*q = ' ';
|
||||
*p++ = *q;
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
n = getfields(cp, line, MAXCONF, 1, "\n");
|
||||
for(i = 0; i < n; i++){
|
||||
if(*line[i] == '#')
|
||||
continue;
|
||||
cp = strchr(line[i], '=');
|
||||
if(cp == nil)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
confname[nconf] = line[i];
|
||||
confval[nconf] = cp;
|
||||
nconf++;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
getconf(char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nconf; i++)
|
||||
if(cistrcmp(confname[i], name) == 0)
|
||||
return confval[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
writeconf(void)
|
||||
{
|
||||
char *p, *q;
|
||||
int n;
|
||||
|
||||
p = getconfenv();
|
||||
|
||||
if(waserror()) {
|
||||
free(p);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
/* convert to name=value\n format */
|
||||
for(q=p; *q; q++) {
|
||||
q += strlen(q);
|
||||
*q = '=';
|
||||
q += strlen(q);
|
||||
*q = '\n';
|
||||
}
|
||||
n = q - p + 1;
|
||||
if(n >= BOOTARGSLEN)
|
||||
error("kernel configuration too large");
|
||||
memset(BOOTLINE, 0, BOOTLINELEN);
|
||||
memmove(BOOTARGS, p, n);
|
||||
poperror();
|
||||
free(p);
|
||||
}
|
||||
|
||||
void
|
||||
confinit(void)
|
||||
{
|
||||
|
@ -332,7 +187,43 @@ mach0init(void)
|
|||
}
|
||||
|
||||
void
|
||||
bootargs(void *base)
|
||||
init0(void)
|
||||
{
|
||||
char buf[2*KNAMELEN];
|
||||
|
||||
up->nerrlab = 0;
|
||||
|
||||
spllo();
|
||||
|
||||
/*
|
||||
* These are o.k. because rootinit is null.
|
||||
* Then early kproc's will have a root and dot.
|
||||
*/
|
||||
up->slash = namec("#/", Atodir, 0, 0);
|
||||
pathclose(up->slash->path);
|
||||
up->slash->path = newpath("/");
|
||||
up->dot = cclone(up->slash);
|
||||
|
||||
chandevinit();
|
||||
|
||||
if(!waserror()){
|
||||
snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
|
||||
ksetenv("terminal", buf, 0);
|
||||
ksetenv("cputype", "amd64", 0);
|
||||
if(cpuserver)
|
||||
ksetenv("service", "cpu", 0);
|
||||
else
|
||||
ksetenv("service", "terminal", 0);
|
||||
setconfenv();
|
||||
poperror();
|
||||
}
|
||||
kproc("alarm", alarmkproc, 0);
|
||||
|
||||
touser(sp);
|
||||
}
|
||||
|
||||
void
|
||||
userbootargs(void *base)
|
||||
{
|
||||
char *argv[8];
|
||||
int i, argc;
|
||||
|
@ -367,47 +258,6 @@ bootargs(void *base)
|
|||
sp -= BY2WD;
|
||||
}
|
||||
|
||||
void
|
||||
init0(void)
|
||||
{
|
||||
int i;
|
||||
char buf[2*KNAMELEN];
|
||||
|
||||
up->nerrlab = 0;
|
||||
|
||||
spllo();
|
||||
|
||||
/*
|
||||
* These are o.k. because rootinit is null.
|
||||
* Then early kproc's will have a root and dot.
|
||||
*/
|
||||
up->slash = namec("#/", Atodir, 0, 0);
|
||||
pathclose(up->slash->path);
|
||||
up->slash->path = newpath("/");
|
||||
up->dot = cclone(up->slash);
|
||||
|
||||
chandevinit();
|
||||
|
||||
if(!waserror()){
|
||||
snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
|
||||
ksetenv("terminal", buf, 0);
|
||||
ksetenv("cputype", "amd64", 0);
|
||||
if(cpuserver)
|
||||
ksetenv("service", "cpu", 0);
|
||||
else
|
||||
ksetenv("service", "terminal", 0);
|
||||
for(i = 0; i < nconf; i++){
|
||||
if(confname[i][0] != '*')
|
||||
ksetenv(confname[i], confval[i], 0);
|
||||
ksetenv(confname[i], confval[i], 1);
|
||||
}
|
||||
poperror();
|
||||
}
|
||||
kproc("alarm", alarmkproc, 0);
|
||||
|
||||
touser(sp);
|
||||
}
|
||||
|
||||
void
|
||||
userinit(void)
|
||||
{
|
||||
|
@ -452,7 +302,7 @@ userinit(void)
|
|||
v = kmap(pg);
|
||||
memset(v, 0, BY2PG);
|
||||
segpage(s, pg);
|
||||
bootargs(v);
|
||||
userbootargs(v);
|
||||
kunmap(v);
|
||||
|
||||
/*
|
||||
|
@ -480,7 +330,7 @@ void
|
|||
main()
|
||||
{
|
||||
mach0init();
|
||||
options();
|
||||
bootargsinit();
|
||||
ioinit();
|
||||
i8250console();
|
||||
quotefmtinstall();
|
||||
|
|
|
@ -80,6 +80,17 @@
|
|||
|
||||
#define MACHSIZE (2*KSTACK)
|
||||
|
||||
/*
|
||||
* Where configuration info is left for the loaded programme.
|
||||
* This will turn into a structure as more is done by the boot loader
|
||||
* (e.g. why parse the .ini file twice?).
|
||||
* There are 3584 bytes available at CONFADDR.
|
||||
*/
|
||||
#define BOOTLINE ((char*)CONFADDR)
|
||||
#define BOOTLINELEN 64
|
||||
#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
|
||||
#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
|
||||
|
||||
/*
|
||||
* known x86 segments (in GDT) and their selectors
|
||||
*/
|
||||
|
|
|
@ -50,6 +50,7 @@ OBJ=\
|
|||
memory.$O\
|
||||
mmu.$O\
|
||||
trap.$O\
|
||||
bootargs.$O\
|
||||
$CONF.root.$O\
|
||||
$CONF.rootc.$O\
|
||||
$DEVS\
|
||||
|
|
Loading…
Reference in a new issue