diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-06-25 22:22:58 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-06-25 22:22:58 +0200 |
commit | aab4e32ce05a26bff7386bb86ffc24589cbe601c (patch) | |
tree | 3ee177109bf3b076b6cccf461cf559c284fa845a /sys/src | |
parent | ffde0eda463e8b908975abcabc5345cfaa1a14f7 (diff) |
pc, pc64: support for multiboot framebuffer, common bootargs and multiboot code
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/pc/bootargs.c | 189 | ||||
-rw-r--r-- | sys/src/9/pc/fns.h | 4 | ||||
-rw-r--r-- | sys/src/9/pc/l.s | 13 | ||||
-rw-r--r-- | sys/src/9/pc/main.c | 232 | ||||
-rw-r--r-- | sys/src/9/pc/mem.h | 11 | ||||
-rw-r--r-- | sys/src/9/pc/mkfile | 1 | ||||
-rw-r--r-- | sys/src/9/pc/screen.c | 33 | ||||
-rw-r--r-- | sys/src/9/pc/screen.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc/vgavesa.c | 71 | ||||
-rw-r--r-- | sys/src/9/pc64/fns.h | 4 | ||||
-rw-r--r-- | sys/src/9/pc64/l.s | 6 | ||||
-rw-r--r-- | sys/src/9/pc64/main.c | 228 | ||||
-rw-r--r-- | sys/src/9/pc64/mem.h | 11 | ||||
-rw-r--r-- | sys/src/9/pc64/mkfile | 1 |
14 files changed, 400 insertions, 405 deletions
diff --git a/sys/src/9/pc/bootargs.c b/sys/src/9/pc/bootargs.c new file mode 100644 index 000000000..ece6f8e33 --- /dev/null +++ b/sys/src/9/pc/bootargs.c @@ -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); +} diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 594d2f553..3710d9291 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -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); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index c2c283793..e28ef9e95 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -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 /* diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index 1e9ec8bb6..c69fb9769 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -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,11 +135,7 @@ 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); @@ -251,6 +143,42 @@ init0(void) } 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 @@ userinit(void) v = tmpmap(pg); memset(v, 0, BY2PG); segpage(s, pg); - bootargs(v); + userbootargs(v); tmpunmap(v); /* @@ -315,82 +243,6 @@ userinit(void) } 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) { char *p; diff --git a/sys/src/9/pc/mem.h b/sys/src/9/pc/mem.h index 7f5b09a16..6de469cb3 100644 --- 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 */ diff --git a/sys/src/9/pc/mkfile b/sys/src/9/pc/mkfile index c6e683e22..62e622b21 100644 --- a/sys/src/9/pc/mkfile +++ b/sys/src/9/pc/mkfile @@ -53,6 +53,7 @@ OBJ=\ memory.$O\ mmu.$O\ trap.$O\ + bootargs.$O\ $CONF.root.$O\ $CONF.rootc.$O\ $DEVS\ diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c index 69018c4fe..20df768fd 100644 --- a/sys/src/9/pc/screen.c +++ b/sys/src/9/pc/screen.c @@ -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); } diff --git a/sys/src/9/pc/screen.h b/sys/src/9/pc/screen.h index 646edd6e2..401d056a3 100644 --- a/sys/src/9/pc/screen.h +++ b/sys/src/9/pc/screen.h @@ -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*); diff --git a/sys/src/9/pc/vgavesa.c b/sys/src/9/pc/vgavesa.c index ceca04406..dbe4d0024 100644 --- a/sys/src/9/pc/vgavesa.c +++ b/sys/src/9/pc/vgavesa.c @@ -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); +} diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index f51d21fe6..481572a3a 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -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); diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index 715e5f432..a1cc976f3 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -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 diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 24d99eea6..179c9e6d0 100644 --- 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 @@ 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,45 +187,8 @@ mach0init(void) } 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 @@ 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); @@ -409,6 +223,42 @@ init0(void) } 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 @@ 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(); diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index a5d1aa368..4c07bf99b 100644 --- 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 */ diff --git a/sys/src/9/pc64/mkfile b/sys/src/9/pc64/mkfile index 8214614a9..bf298306b 100644 --- a/sys/src/9/pc64/mkfile +++ b/sys/src/9/pc64/mkfile @@ -50,6 +50,7 @@ OBJ=\ memory.$O\ mmu.$O\ trap.$O\ + bootargs.$O\ $CONF.root.$O\ $CONF.rootc.$O\ $DEVS\ |