pc, pc64: support for multiboot framebuffer, common bootargs and multiboot code

This commit is contained in:
cinap_lenrek 2017-06-25 22:22:58 +02:00
parent ffde0eda46
commit aab4e32ce0
14 changed files with 400 additions and 405 deletions

189
sys/src/9/pc/bootargs.c Normal file
View 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);
}

View file

@ -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);

View file

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

View file

@ -11,131 +11,28 @@
#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();
screeninit();
print("\nPlan 9\n");
trapinit0();
i8253init();
cpuidentify();
@ -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)
{

View file

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

View file

@ -53,6 +53,7 @@ OBJ=\
memory.$O\
mmu.$O\
trap.$O\
bootargs.$O\
$CONF.root.$O\
$CONF.rootc.$O\
$DEVS\

View file

@ -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);
}

View file

@ -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*);

View file

@ -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);
}

View file

@ -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);

View file

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

View file

@ -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();

View file

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

View file

@ -50,6 +50,7 @@ OBJ=\
memory.$O\
mmu.$O\
trap.$O\
bootargs.$O\
$CONF.root.$O\
$CONF.rootc.$O\
$DEVS\