ref: aab4e32ce05a26bff7386bb86ffc24589cbe601c
parent: ffde0eda463e8b908975abcabc5345cfaa1a14f7
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jun 25 18:22:58 EDT 2017
pc, pc64: support for multiboot framebuffer, common bootargs and multiboot code
--- /dev/null
+++ b/sys/src/9/pc/bootargs.c
@@ -1,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);
+}
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -8,7 +8,7 @@
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 @@
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 @@
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);
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -42,8 +42,8 @@
*/
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 @@
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 @@
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
/*
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -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();
@@ -135,7 +32,7 @@
screeninit();
print("\nPlan 9\n");
-
+
trapinit0();
i8253init();
cpuidentify();
@@ -213,7 +110,6 @@
void
init0(void)
{
- int i;
char buf[2*KNAMELEN];
up->nerrlab = 0;
@@ -239,11 +135,7 @@
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);
@@ -251,6 +143,42 @@
}
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)
{
void *v;
@@ -294,7 +222,7 @@
v = tmpmap(pg);
memset(v, 0, BY2PG);
segpage(s, pg);
- bootargs(v);
+ userbootargs(v);
tmpunmap(v);
/*
@@ -312,82 +240,6 @@
tmpunmap(v);
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
--- a/sys/src/9/pc/mem.h
+++ b/sys/src/9/pc/mem.h
@@ -78,6 +78,17 @@
*/
/*
+ * 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
*/
#define NULLSEG 0 /* null segment */
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -53,6 +53,7 @@
memory.$O\
mmu.$O\
trap.$O\
+ bootargs.$O\
$CONF.root.$O\
$CONF.rootc.$O\
$DEVS\
--- a/sys/src/9/pc/screen.c
+++ b/sys/src/9/pc/screen.c
@@ -587,6 +587,36 @@
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 @@
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);
}
--- a/sys/src/9/pc/screen.h
+++ b/sys/src/9/pc/screen.h
@@ -147,6 +147,7 @@
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*);
--- a/sys/src/9/pc/vgavesa.c
+++ b/sys/src/9/pc/vgavesa.c
@@ -31,6 +31,17 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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);
+}
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -8,7 +8,7 @@
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 @@
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* 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);
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -37,8 +37,8 @@
*/
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 @@
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
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -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 @@
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,45 +187,8 @@
}
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;
- }
-
- /* 8 byte word align stack */
- sp = (char*)((uintptr)sp & ~7);
-
- /* 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
init0(void)
{
- int i;
char buf[2*KNAMELEN];
up->nerrlab = 0;
@@ -396,11 +214,7 @@
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);
@@ -409,6 +223,42 @@
}
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;
+ }
+
+ /* 8 byte word align stack */
+ sp = (char*)((uintptr)sp & ~7);
+
+ /* 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)
{
void *v;
@@ -452,7 +302,7 @@
v = kmap(pg);
memset(v, 0, BY2PG);
segpage(s, pg);
- bootargs(v);
+ userbootargs(v);
kunmap(v);
/*
@@ -480,7 +330,7 @@
main()
{
mach0init();
- options();
+ bootargsinit();
ioinit();
i8250console();
quotefmtinstall();
--- a/sys/src/9/pc64/mem.h
+++ b/sys/src/9/pc64/mem.h
@@ -81,6 +81,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
*/
#define NULLSEG 0 /* null segment */
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -50,6 +50,7 @@
memory.$O\
mmu.$O\
trap.$O\
+ bootargs.$O\
$CONF.root.$O\
$CONF.rootc.$O\
$DEVS\