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:
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.