vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

commit 537b928eef0c6c96a53832be60f06fae0206680c
parent b1304f7ab2facdaec4d97b480535c1633d03247c
Author: Jesus Galan Lopez (yiyus) <yiyu.jgl@gmail.com>
Date:   Tue, 25 May 2010 08:06:52 +0200

BLS support for plan9.ini parsing and local file systems

Diffstat:
src/9vx/Makefrag | 20+++++++++++++++++++-
src/9vx/a/devsd.c | 16+++++++++++++++-
src/9vx/a/dosfs.h | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/9vx/a/fns.ed | 3+++
src/9vx/a/fns.h | 3+++
src/9vx/a/fs.h | 38++++++++++++++++++++++++++++++++++++++
src/9vx/a/kfs.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/9vx/a/part.c | 341+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/9vx/a/sd.h | 5+++++
src/9vx/bootcode.9 | 0
src/9vx/conf.c | 352+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/9vx/fossil.9 | 0
src/9vx/ipconfig.9 | 0
src/9vx/main.c | 18+++++++++++++++++-
src/9vx/sdloop.c | 53++++++++++++++++++++++++++++++++++++++++++++++++++---
src/9vx/venti.9 | 0
16 files changed, 962 insertions(+), 6 deletions(-)

diff --git a/src/9vx/Makefrag b/src/9vx/Makefrag @@ -26,6 +26,7 @@ all: 9vx/9vx PLAN9_OBJS = \ $(addprefix 9vx/, \ bootcode.o \ + conf.o \ devaudio.o \ devaudio-$(PLAN9AUDIO).o \ devfs-posix.o \ @@ -36,6 +37,8 @@ PLAN9_OBJS = \ devram.o \ devtab.o \ factotum.o \ + fossil.o \ + ipconfig.o \ kprocdev.o \ label.o \ main.o \ @@ -47,6 +50,7 @@ PLAN9_OBJS = \ time.o \ trap.o \ tty.o \ + venti.o \ vx32.o \ ) @@ -91,6 +95,7 @@ PLAN9_A_OBJS = \ page.o \ parse.o \ parseip.o \ + part.o \ pgrp.o \ print.o \ proc.o \ @@ -176,6 +181,15 @@ PLAN9_DEPS = \ 9vx/factotum.S: 9vx/data2s 9vx/factotum.9 ./9vx/data2s factotum < 9vx/factotum.9 >$@_ && mv $@_ $@ +9vx/fossil.S: 9vx/data2s 9vx/fossil.9 + ./9vx/data2s fossil < 9vx/fossil.9 >$@_ && mv $@_ $@ + +9vx/ipconfig.S: 9vx/data2s 9vx/ipconfig.9 + ./9vx/data2s ipconfig < 9vx/ipconfig.9 > $@_ && mv $@_ $@ + +9vx/venti.S: 9vx/data2s 9vx/venti.9 + ./9vx/data2s venti < 9vx/venti.9 > $@_ && mv $@_ $@ + 9vx/a/errstr.h: 9vx/a/error.h sed 's/extern //; s!;.*/\* ! = "!; s! \*\/!";!' 9vx/a/error.h >9vx/a/errstr.h @@ -199,7 +213,11 @@ CLEAN_FILES += \ 9vx/a/errstr.h \ 9vx/9vx \ 9vx/data2s \ - 9vx/bootcode.S + 9vx/bootcode.S \ + 9vx/factotum.S \ + 9vx/fossil.S \ + 9vx/ipconfig.S \ + 9vx/venti.S include 9vx/libdraw/Makefrag include 9vx/libmemlayer/Makefrag diff --git a/src/9vx/a/devsd.c b/src/9vx/a/devsd.c @@ -72,7 +72,7 @@ enum { ((p)<<PartSHIFT)|((t)<<TypeSHIFT)) -static void +void sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end) { SDpart *pp; @@ -135,6 +135,19 @@ sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end) pp->valid = 1; } +SDpart* +sdfindpart(SDunit *unit, char *name) +{ + int i; + + for(i=0; i<unit->npart; i++) { + if(strcmp(unit->part[i].perm.name, name) == 0){ + return &unit->part[i]; + } + } + return nil; +} + static void sddelpart(SDunit* unit, char* name) { @@ -198,6 +211,7 @@ sdinitpart(SDunit* unit) if(unit->sectors){ sdincvers(unit); sdaddpart(unit, "data", 0, unit->sectors); + partition(unit); #if 0 /* * Use partitions passed from boot program, diff --git a/src/9vx/a/dosfs.h b/src/9vx/a/dosfs.h @@ -0,0 +1,62 @@ +typedef struct Dosboot Dosboot; +typedef struct Dos Dos; +typedef struct Dosdir Dosdir; +typedef struct Dosfile Dosfile; +typedef struct Dospart Dospart; + +struct Dospart +{ + uchar flag; /* active flag */ + uchar shead; /* starting head */ + uchar scs[2]; /* starting cylinder/sector */ + uchar type; /* partition type */ + uchar ehead; /* ending head */ + uchar ecs[2]; /* ending cylinder/sector */ + uchar start[4]; /* starting sector */ + uchar len[4]; /* length in sectors */ +}; + +#define FAT12 0x01 +#define FAT16 0x04 +#define EXTEND 0x05 +#define FATHUGE 0x06 +#define FAT32 0x0b +#define FAT32X 0x0c +#define EXTHUGE 0x0f +#define DMDDO 0x54 +#define PLAN9 0x39 +#define LEXTEND 0x85 + +struct Dosfile{ + Dos *dos; /* owning dos file system */ + char name[8]; + char ext[3]; + uchar attr; + long length; + long pstart; /* physical start cluster address */ + long pcurrent; /* physical current cluster address */ + long lcurrent; /* logical current cluster address */ + long offset; +}; + +struct Dos{ + long start; /* start of file system */ + int sectsize; /* in bytes */ + int clustsize; /* in sectors */ + int clustbytes; /* in bytes */ + int nresrv; /* sectors */ + int nfats; /* usually 2 */ + int rootsize; /* number of entries */ + int volsize; /* in sectors */ + int mediadesc; + int fatsize; /* in sectors */ + int fatclusters; + int fatbits; /* 12 or 16 */ + long fataddr; /* sector number */ + long rootaddr; + long rootclust; + long dataaddr; + long freeptr; +}; + +extern int dosinit(Fs*); diff --git a/src/9vx/a/fns.ed b/src/9vx/a/fns.ed @@ -16,4 +16,7 @@ int tailkmesg(char*, int); void trap(Ureg*); void uartecho(char*, int); void uartinit(int); + +#define GSHORT(p) (((p)[1]<<8)|(p)[0]) +#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p)) . diff --git a/src/9vx/a/fns.h b/src/9vx/a/fns.h @@ -167,6 +167,9 @@ void *uvalidaddr(ulong addr, ulong len, int write); int isuaddr(void*); void setsigsegv(int invx32); +#define GSHORT(p) (((p)[1]<<8)|(p)[0]) +#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p)) + void plock(Psleep*); void punlock(Psleep*); void pwakeup(Psleep*); diff --git a/src/9vx/a/fs.h b/src/9vx/a/fs.h @@ -0,0 +1,38 @@ +typedef struct File File; +typedef struct Fs Fs; + +#include "dosfs.h" +#include "kfs.h" + +struct File{ + union{ + Dosfile dos; + Kfsfile kfs; + int walked; + }; + Fs *fs; + char *path; +}; + +struct Fs{ + union { + Dos dos; + Kfs kfs; + }; + int dev; /* device id */ + long (*diskread)(Fs*, void*, long); /* disk read routine */ + vlong (*diskseek)(Fs*, vlong); /* disk seek routine */ + long (*read)(File*, void*, long); + int (*walk)(File*, char*); + File root; +}; + +/* +extern int chatty; +extern int dotini(Fs*); +extern int fswalk(Fs*, char*, File*); +extern int fsread(File*, void*, long); +extern int fsboot(Fs*, char*, Boot*); +*/ + +#define BADPTR(x) ((ulong)x < 0x80000000) diff --git a/src/9vx/a/kfs.h b/src/9vx/a/kfs.h @@ -0,0 +1,57 @@ +typedef struct Qid9p1 Qid9p1; +typedef struct Dentry Dentry; +typedef struct Kfsfile Kfsfile; +typedef struct Kfs Kfs; + +/* DONT TOUCH, this is the disk structure */ +struct Qid9p1 +{ + long path; + long version; +}; + +#define NAMELEN 28 /* size of names */ +#define NDBLOCK 6 /* number of direct blocks in Dentry */ + +/* DONT TOUCH, this is the disk structure */ +struct Dentry +{ + char name[NAMELEN]; + short uid; + short gid; + ushort mode; +/* + #define DALLOC 0x8000 + #define DDIR 0x4000 + #define DAPND 0x2000 + #define DLOCK 0x1000 + #define DREAD 0x4 + #define DWRITE 0x2 + #define DEXEC 0x1 +*/ + Qid9p1 qid; + long size; + long dblock[NDBLOCK]; + long iblock; + long diblock; + long atime; + long mtime; +}; + +struct Kfsfile +{ + Dentry; + long off; +}; + +struct Kfs +{ + int RBUFSIZE; + int BUFSIZE; + int DIRPERBUF; + int INDPERBUF; + int INDPERBUF2; +}; + +extern int kfsinit(Fs*); + diff --git a/src/9vx/a/part.c b/src/9vx/a/part.c @@ -0,0 +1,341 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#include "sd.h" +#include "fs.h" + +enum { + Npart = 32 +}; + +uchar *mbrbuf, *partbuf; +int nbuf; +#define trace 0 + +int +tsdbio(SDunit *unit, SDpart *part, void *a, vlong off, int mbr) +{ + uchar *b; + + if(unit->dev->ifc->bio(unit, 0, 0, a, 1, (off/unit->secsize) + part->start) != unit->secsize){ + if(trace) + print("%s: read %lud at %lld failed\n", unit->dev->name, + unit->secsize, (vlong)part->start*unit->secsize+off); + return -1; + } + b = a; + if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){ + if(trace) + print("%s: bad magic %.2ux %.2ux at %lld\n", + unit->dev->name, b[0x1FE], b[0x1FF], + (vlong)part->start*unit->secsize+off); + return -1; + } + return 0; +} + +/* + * read partition table. The partition table is just ascii strings. + */ +#define MAGIC "plan9 partitions" +static void +oldp9part(SDunit *unit) +{ + SDpart *pp; + char *field[3], *line[Npart+1]; + ulong n, start, end; + int i; + + /* + * We have some partitions already. + */ + pp = &unit->part[unit->npart]; + + /* + * We prefer partition tables on the second to last sector, + * but some old disks use the last sector instead. + */ + pp->start = unit->sectors - 2; + pp->end = unit->sectors - 1; + + if(tsdbio(unit, pp, partbuf, 0, 0) < 0) + return; + + if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) { + /* not found on 2nd last sector; look on last sector */ + pp->start++; + pp->end++; + if(tsdbio(unit, pp, partbuf, 0, 0) < 0) + return; + if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) + return; + print("%s: using old plan9 partition table on last sector\n", unit->dev->name); + }else + print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->dev->name); + + /* we found a partition table, so add a partition partition */ + unit->npart++; + partbuf[unit->secsize-1] = '\0'; + + /* + * parse partition table + */ + n = getfields((char*)partbuf, line, Npart+1, 0, "\n"); + if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){ + for(i = 1; i < n && unit->npart < SDnpart; i++){ + if(getfields(line[i], field, 3, 0, " ") != 3) + break; + start = strtoull(field[1], 0, 0); + end = strtoull(field[2], 0, 0); + if(start >= end || end > unit->sectors) + break; + sdaddpart(unit, field[0], start, end); + } + } +} + +static void +p9part(SDunit *unit, char *name) +{ + SDpart *p; + char *field[4], *line[Npart+1]; + uvlong start, end; + int i, n; + + p = sdfindpart(unit, name); + if(p == nil) + return; + + if(tsdbio(unit, p, partbuf, unit->secsize, 0) < 0) + return; + partbuf[unit->secsize-1] = '\0'; + + if(strncmp((char*)partbuf, "part ", 5) != 0) + return; + + n = getfields((char*)partbuf, line, Npart+1, 0, "\n"); + if(n == 0) + return; + for(i = 0; i < n /* && unit->npart < SDnpart */; i++){ + if(strncmp(line[i], "part ", 5) != 0) + break; + if(getfields(line[i], field, 4, 0, " ") != 4) + break; + start = strtoull(field[2], 0, 0); + end = strtoull(field[3], 0, 0); + if(start >= end || end > unit->sectors) + break; + sdaddpart(unit, field[1], p->start+start, p->start+end); + } +} + +int +isdos(int t) +{ + return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X; +} + +int +isextend(int t) +{ + return t==EXTEND || t==EXTHUGE || t==LEXTEND; +} + +/* + * Fetch the first dos and all plan9 partitions out of the MBR partition table. + * We return -1 if we did not find a plan9 partition. + */ +static int +mbrpart(SDunit *unit) +{ + Dospart *dp; + ulong taboffset, start, end; + ulong firstxpart, nxtxpart; + int havedos, i, nplan9; + char name[10]; + + taboffset = 0; + dp = (Dospart*)&mbrbuf[0x1BE]; + if(1) { + /* get the MBR (allowing for DMDDO) */ + if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0) + return -1; + for(i=0; i<4; i++) + if(dp[i].type == DMDDO) { + if(trace) + print("DMDDO partition found\n"); + taboffset = 63; + if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0) + return -1; + i = -1; /* start over */ + } + } + + /* + * Read the partitions, first from the MBR and then + * from successive extended partition tables. + */ + nplan9 = 0; + havedos = 0; + firstxpart = 0; + for(;;) { + if(tsdbio(unit, &unit->part[0], mbrbuf, (vlong)taboffset*unit->secsize, 1) < 0) + return -1; + if(trace) { + if(firstxpart) + print("%s ext %lud ", unit->dev->name, taboffset); + else + print("%s mbr ", unit->dev->name); + } + nxtxpart = 0; + for(i=0; i<4; i++) { + if(trace) + print("dp %d...", dp[i].type); + start = taboffset+GLONG(dp[i].start); + end = start+GLONG(dp[i].len); + + if(dp[i].type == PLAN9) { + if(nplan9 == 0) + strcpy(name, "plan9"); + else + sprint(name, "plan9.%d", nplan9); + sdaddpart(unit, name, start, end); + p9part(unit, name); + nplan9++; + } + + /* + * We used to take the active partition (and then the first + * when none are active). We have to take the first here, + * so that the partition we call ``dos'' agrees with the + * partition disk/fdisk calls ``dos''. + */ + if(havedos==0 && isdos(dp[i].type)){ + havedos = 1; + sdaddpart(unit, "dos", start, end); + } + + /* nxtxpart is relative to firstxpart (or 0), not taboffset */ + if(isextend(dp[i].type)){ + nxtxpart = start-taboffset+firstxpart; + if(trace) + print("link %lud...", nxtxpart); + } + } + if(trace) + print("\n"); + + if(!nxtxpart) + break; + if(!firstxpart) + firstxpart = nxtxpart; + taboffset = nxtxpart; + } + return nplan9 ? 0 : -1; +} + +/* + * To facilitate booting from CDs, we create a partition for + * the boot floppy image embedded in a bootable CD. + */ +static int +part9660(SDunit *unit) +{ + uchar buf[2048]; + ulong a, n; + uchar *p; + + if(unit->secsize != 2048) + return -1; + + if(unit->dev->ifc->bio(unit, 0, 0, buf, 2048/unit->secsize, (17*2048)/unit->secsize) < 0) + return -1; + + if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0) + return -1; + + + p = buf+0x47; + a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); + + if(unit->dev->ifc->bio(unit, 0, 0, buf, 2048/unit->secsize, (a*2048)/unit->secsize) < 0) + return -1; + + if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0 + || memcmp(buf+30, "\x55\xAA", 2) != 0 + || buf[0x20] != 0x88) + return -1; + + p = buf+0x28; + a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); + + switch(buf[0x21]){ + case 0x01: + n = 1200*1024; + break; + case 0x02: + n = 1440*1024; + break; + case 0x03: + n = 2880*1024; + break; + default: + return -1; + } + n /= 2048; + + print("found partition %s!cdboot; %lud+%lud\n", unit->dev->name, a, n); + sdaddpart(unit, "cdboot", a, a+n); + return 0; +} + +enum { + NEW = 1<<0, + OLD = 1<<1 +}; + +void +partition(SDunit *unit) +{ + int type; + char *p; + + if(unit->part == 0) + return; + + if(part9660(unit) == 0) + return; + + p = "new"; + + if(p != nil && strncmp(p, "new", 3) == 0) + type = NEW; + else if(p != nil && strncmp(p, "old", 3) == 0) + type = OLD; + else + type = NEW|OLD; + + if(nbuf < unit->secsize) { + free(mbrbuf); + free(partbuf); + mbrbuf = malloc(unit->secsize); + partbuf = malloc(unit->secsize); + if(mbrbuf==nil || partbuf==nil) { + free(mbrbuf); + free(partbuf); + partbuf = mbrbuf = nil; + nbuf = 0; + return; + } + nbuf = unit->secsize; + } + + if((type & NEW) && mbrpart(unit) >= 0){ + /* nothing to do */; + } + else if(type & OLD) + oldp9part(unit); +} diff --git a/src/9vx/a/sd.h b/src/9vx/a/sd.h @@ -129,9 +129,14 @@ extern void sdadddevs(SDev*); extern int sdsetsense(SDreq*, int, int, int, int); extern int sdmodesense(SDreq*, uchar*, void*, int); extern int sdfakescsi(SDreq*, void*, int); +extern void sdaddpart(SDunit*, char*, uvlong, uvlong); +extern SDpart* sdfindpart(SDunit*, char*); /* sdscsi.c */ extern int scsiverify(SDunit*); extern int scsionline(SDunit*); extern long scsibio(SDunit*, int, int, void*, long, uvlong); extern SDev* scsiid(SDev*, SDifc*); + +/* part.c */ +extern void partition(SDunit*); diff --git a/src/9vx/bootcode.9 b/src/9vx/bootcode.9 Binary files differ. diff --git a/src/9vx/conf.c b/src/9vx/conf.c @@ -0,0 +1,352 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#include "fs.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. + * + * The low-level boot routines in l.s leave data for us at CONFADDR, + * which we pick up before reading the plan9.ini file. + */ +#define BOOTLINELEN 64 +#define BOOTARGSLEN (3584-0x200-BOOTLINELEN) +#define MAXCONF 100 + +extern char **ini; + +typedef struct { + char* name; + int start; + int end; +} Mblock; + +typedef struct { + char* tag; + Mblock* mb; +} Mitem; + +static Mblock mblock[MAXCONF]; +static int nmblock; +static Mitem mitem[MAXCONF]; +static int nmitem; +static char* mdefault; +static char mdefaultbuf[10]; +static int mtimeout; + +static void +getstr(char* prompt, char* buf, int n, char* def, int timeout) +{ + char *p; + int i; + char c; + + if(def == nil) + print("%s: ", prompt); + else + print("%s[default==%s]: ", prompt, def); + for(p = buf, i = 0; i < n-1;){ + qread(kbdq, &c, 1); + switch(c){ + case '\b': + if(i > 0){ + --p; + --i; + } + break; + case 0x15: + p = buf; + i = 0; + break; + case '\n': + break; + default: + *p++ = c; + ++i; + break; + } + if(c == '\n') + break; + } + *p = 0; + if(i == 0) + strcpy(buf, def); +} + +static char* +comma(char* line, char** residue) +{ + char *q, *r; + + if((q = strchr(line, ',')) != nil){ + *q++ = 0; + if(*q == ' ') + q++; + } + *residue = q; + + if((r = strchr(line, ' ')) != nil) + *r = 0; + + if(*line == ' ') + line++; + return line; +} + +static Mblock* +findblock(char* name, char** residue) +{ + int i; + char *p; + + p = comma(name, residue); + for(i = 0; i < nmblock; i++){ + if(strcmp(p, mblock[i].name) == 0) + return &mblock[i]; + } + return nil; +} + +static Mitem* +finditem(char* name, char** residue) +{ + int i; + char *p; + + p = comma(name, residue); + for(i = 0; i < nmitem; i++){ + if(strcmp(p, mitem[i].mb->name) == 0) + return &mitem[i]; + } + return nil; +} + +static void +parsemenu(char* str, int len) +{ + Mitem *mi; + Mblock *mb, *menu; + char buf[20], scratch[BOOTARGSLEN], *p, *q, *line[MAXCONF]; + int i, inblock, n, show; + + inblock = 0; + menu = nil; + memmove(scratch, str, len); + n = getfields(scratch, line, MAXCONF, 0, "\n"); + if(n >= MAXCONF) + print("warning: possibly too many lines in plan9.ini\n"); + for(i = 0; i < n; i++){ + p = line[i]; + if(inblock && *p == '['){ + mblock[nmblock].end = i; + if(strcmp(mblock[nmblock].name, "menu") == 0) + menu = &mblock[nmblock]; + nmblock++; + inblock = 0; + } + if(*p == '['){ + if(nmblock == 0 && i != 0){ + mblock[nmblock].name = "common"; + mblock[nmblock].start = 0; + mblock[nmblock].end = i; + nmblock++; + } + q = strchr(p+1, ']'); + if(q == nil || *(q+1) != 0){ + print("malformed menu block header - %s\n", p); + return; + } + *q = 0; + mblock[nmblock].name = p+1; + mblock[nmblock].start = i+1; + inblock = 1; + } + } + + if(inblock){ + mblock[nmblock].end = i; + nmblock++; + } + if(menu == nil) + return; + if(nmblock < 2){ + print("incomplete menu specification\n"); + return; + } + + for(i = menu->start; i < menu->end; i++){ + p = line[i]; + if(strncmp(p, "menuitem=", 9) == 0){ + p += 9; + if((mb = findblock(p, &q)) == nil){ + print("no block for menuitem %s\n", p); + return; + } + if(q != nil) + mitem[nmitem].tag = q; + else + mitem[nmitem].tag = mb->name; + mitem[nmitem].mb = mb; + nmitem++; + } + else if(strncmp(p, "menudefault=", 12) == 0){ + p += 12; + if((mi = finditem(p, &q)) == nil){ + print("no item for menudefault %s\n", p); + return; + } + if(q != nil) + mtimeout = strtol(q, 0, 0); + sprint(mdefaultbuf, "%ld", mi-mitem+1); + mdefault = mdefaultbuf; + } + else if(strncmp(p, "menuconsole=", 12) == 0){ + p += 12; + p = comma(p, &q); + /* consinit(p, q); */ + } + else{ + print("invalid line in [menu] block - %s\n", p); + return; + } + } + +again: + print("\nPlan 9 Startup Menu:\n====================\n"); + for(i = 0; i < nmitem; i++) + print(" %d. %s\n", i+1, mitem[i].tag); + for(;;){ + getstr("Selection", buf, sizeof(buf), mdefault, mtimeout); + mtimeout = 0; + i = strtol(buf, &p, 0)-1; + if(i < 0 || i >= nmitem) + goto again; + switch(*p){ + case 'p': + case 'P': + show = 1; + print("\n"); + break; + case 0: + show = 0; + break; + default: + continue; + + } + mi = &mitem[i]; + + p = str; + p += sprint(p, "menuitem=%s\n", mi->mb->name); + for(i = 0; i < nmblock; i++){ + mb = &mblock[i]; + if(mi->mb != mb && strcmp(mb->name, "common") != 0) + continue; + for(n = mb->start; n < mb->end; n++) + p += sprint(p, "%s\n", line[n]); + } + + if(show){ + for(q = str; q < p; q += i){ + if((i = print(q)) <= 0) + break; + } + goto again; + } + break; + } + print("\n"); +} + +/* + * read configuration file + */ +static char inibuf[BOOTARGSLEN]; + +int +dotini(char *fn) +{ + int blankline, i, incomment, inspace, n, fd; + char *cp, *p, *q, *line[MAXCONF]; + + if((fd = open(fn, OREAD)) < 0) + return -1; + + cp = inibuf; + *cp = 0; + n = read(fd, cp, BOOTARGSLEN-1); + close(fd); + if(n <= 0) + return -1; + + cp[n] = 0; + + /* + * Strip out '\r', change '\t' -> ' '. + * Change runs of spaces into single spaces. + * Strip out trailing spaces, blank lines. + * + * We do this before we make the copy so that if we + * need to change the copy, it is already fairly clean. + * The main need is in the case when plan9.ini has been + * padded with lots of trailing spaces, as is the case + * for those created during a distribution install. + */ + p = cp; + blankline = 1; + incomment = inspace = 0; + for(q = cp; *q; q++){ + if(*q == '\r') + continue; + if(*q == '\t') + *q = ' '; + if(*q == ' '){ + inspace = 1; + continue; + } + if(*q == '\n'){ + if(!blankline){ + if(!incomment) + *p++ = '\n'; + blankline = 1; + } + incomment = inspace = 0; + continue; + } + if(inspace){ + if(!blankline && !incomment) + *p++ = ' '; + inspace = 0; + } + if(blankline && *q == '#') + incomment = 1; + blankline = 0; + if(!incomment) + *p++ = *q; + } + if(p > cp && p[-1] != '\n') + *p++ = '\n'; + *p++ = 0; + n = p-cp; + + parsemenu(cp, n); + + n = getfields(cp, line, MAXCONF, 0, "\n"); + for(i = 0; i < n; i++){ + cp = strchr(line[i], '='); + if(cp == 0) + continue; + *cp++ = 0; + if(cp - line[i] >= NAMELEN+1) + *(line[i]+NAMELEN-1) = 0; + ksetenv(line[i], cp, 0); + } + return 0; +} diff --git a/src/9vx/fossil.9 b/src/9vx/fossil.9 Binary files differ. diff --git a/src/9vx/ipconfig.9 b/src/9vx/ipconfig.9 Binary files differ. diff --git a/src/9vx/main.c b/src/9vx/main.c @@ -42,6 +42,7 @@ char* argv0; char* conffile = "9vx"; Conf conf; +static char* inifile; static int bootboot; /* run /boot/boot instead of bootscript */ static int initrc; /* run rc instead of init */ static char* username; @@ -62,7 +63,8 @@ static char* findroot(void); void usage(void) { - fprint(2, "usage: 9vx [-gt] [-r root] [-u user]\n"); + // TODO(yy): add debug and other options by ron + fprint(2, "usage: 9vx [-bgit] [-r root] [-u user] [-p ini file]\n"); exit(1); } @@ -132,6 +134,9 @@ main(int argc, char **argv) case 'i': initrc = 1; break; + case 'p': + inifile = EARGF(usage()); + break; case 'r': localroot = EARGF(usage()); break; @@ -304,6 +309,12 @@ bootinit(void) */ extern uchar factotumcode[]; extern long factotumlen; + extern uchar fossilcode[]; + extern long fossillen; + extern uchar venticode[]; + extern long ventilen; + extern uchar ipconfigcode[]; + extern long ipconfiglen; if(bootboot){ extern uchar bootcode[]; @@ -314,6 +325,9 @@ bootinit(void) else addbootfile("boot", (uchar*)bootscript, strlen(bootscript)); addbootfile("factotum", factotumcode, factotumlen); + addbootfile("fossil", fossilcode, fossillen); + addbootfile("venti", venticode, ventilen); + addbootfile("ipconfig", ipconfigcode, ipconfiglen); } static uchar *sp; /* user stack of init proc */ @@ -484,6 +498,8 @@ init0(void) ksetenv("service", "terminal", 0); ksetenv("user", username, 0); ksetenv("sysname", "vx32", 0); + if(inifile) + dotini(inifile); /* if we're not running /boot/boot, mount / and create /srv/boot */ if(!bootboot){ diff --git a/src/9vx/sdloop.c b/src/9vx/sdloop.c @@ -22,6 +22,7 @@ struct Ctlr{ Chan *c; int mode; uvlong qidpath; + char fn[20]; }; static Lock ctlrlock; @@ -30,9 +31,47 @@ static Ctlr *ctlrtail; SDifc sdloopifc; +static void +loopopen(Ctlr *c) +{ + if(c->c == nil) + c->c = namec(c->fn, Aopen, c->mode, 0); +} + static SDev* looppnp(void) { + struct stat sbuf; + char c, c2; + char fn[20]; + + for(c = 'a'; c <= 'j'; ++c){ + sprint(fn, "#Z/dev/sd%c", c); + if(stat(fn+2, &sbuf) == 0) + loopdev(fn, ORDWR); + } + for(c = '0'; c <= '9'; ++c){ + sprintf(fn, "#Z/dev/sd%c",c); + if(stat(fn+2, &sbuf) == 0) + loopdev(fn, ORDWR); + } + for(c = 'a'; c <= 'j'; ++c){ + sprint(fn, "#Z/dev/hd%c", c); + if(stat(fn+2, &sbuf) == 0) + loopdev(fn, ORDWR); + } + for(c = '0'; c <= '9'; ++c){ + sprint(fn, "#Z/dev/wd%c", c); + if(stat(fn+2, &sbuf) == 0) + loopdev(fn, ORDWR); + } + for(c = '0'; c <= '8'; ++c){ + for(c2 = '0'; c2 <= '8'; ++c2){ + sprint(fn, "#Z/dev/cciss/c%cd%c", c, c2); + if(stat(fn+2, &sbuf) == 0) + loopdev(fn, ORDWR); + } + } return nil; } @@ -69,6 +108,7 @@ looponline(SDunit *unit) sdev = unit->dev; ctlr = sdev->ctlr; + loopopen(ctlr); c = ctlr->c; n = devtab[c->type]->stat(c, buf, sizeof buf); if(convM2D(buf, n, &dir, nil) == 0) @@ -99,6 +139,7 @@ looprio(SDreq *r) unit = r->unit; sdev = unit->dev; ctlr = sdev->ctlr; + loopopen(ctlr); cmd = r->cmd; if((status = sdfakescsi(r, nil, 0)) != SDnostatus){ @@ -141,6 +182,7 @@ looprctl(SDunit *unit, char *p, int l) char *e, *op; ctlr = unit->dev->ctlr; + loopopen(ctlr); e = p+l; op = p; @@ -170,7 +212,8 @@ loopclear1(Ctlr *ctlr) ctlrtail = ctlr->prev; unlock(&ctlrlock); - cclose(ctlr->c); + if(ctlr->c) + cclose(ctlr->c); free(ctlr); } @@ -187,6 +230,7 @@ looprtopctl(SDev *s, char *p, char *e) char *r; c = s->ctlr; + loopopen(c); r = "ro"; if(c->mode == ORDWR) r = "rw"; @@ -219,9 +263,9 @@ loopdev(char *name, int mode) Ctlr *volatile ctlr; SDev *volatile sdev; - c = namec(name, Aopen, mode, 0); ctlr = nil; sdev = nil; +/* if(waserror()){ cclose(c); if(ctlr) @@ -230,6 +274,7 @@ loopdev(char *name, int mode) free(sdev); nexterror(); } +*/ ctlr = smalloc(sizeof *ctlr); sdev = smalloc(sizeof *sdev); @@ -238,9 +283,11 @@ loopdev(char *name, int mode) sdev->nunit = 1; sdev->idno = '0'; ctlr->sdev = sdev; - ctlr->c = c; + strcpy(ctlr->fn, name); ctlr->mode = mode; +/* poperror(); +*/ lock(&ctlrlock); ctlr->next = nil; diff --git a/src/9vx/venti.9 b/src/9vx/venti.9 Binary files differ.