Initial import of the new boot(8). Change pccd and pcf to use it.

This commit is contained in:
iru 2011-04-16 17:42:16 -03:00
parent 4d4fc2ca34
commit 478d102443
26 changed files with 586 additions and 1760 deletions

View file

@ -2,67 +2,6 @@
#include <libc.h>
#include <../boot/boot.h>
/*
int
plumb(char *dir, char *dest, int *efd, char *here)
{
char buf[128];
char name[128];
int n;
sprint(name, "%s/clone", dir);
efd[0] = open(name, ORDWR);
if(efd[0] < 0)
return -1;
n = read(efd[0], buf, sizeof(buf)-1);
if(n < 0){
close(efd[0]);
return -1;
}
buf[n] = 0;
sprint(name, "%s/%s/data", dir, buf);
if(here){
sprint(buf, "announce %s", here);
if(sendmsg(efd[0], buf) < 0){
close(efd[0]);
return -1;
}
}
sprint(buf, "connect %s", dest);
if(sendmsg(efd[0], buf) < 0){
close(efd[0]);
return -1;
}
efd[1] = open(name, ORDWR);
if(efd[1] < 0){
close(efd[0]);
return -1;
}
return efd[1];
}
*/
int
sendmsg(int fd, char *msg)
{
int n;
n = strlen(msg);
if(write(fd, msg, n) != n)
return -1;
return 0;
}
void
warning(char *s)
{
char buf[ERRMAX];
buf[0] = '\0';
errstr(buf, sizeof buf);
fprint(2, "boot: %s: %s\n", s, buf);
}
void
fatal(char *s)
{
@ -90,6 +29,33 @@ readfile(char *name, char *buf, int len)
return 0;
}
void
run(char *file, ...)
{
char buf[64];
Waitmsg *w;
int pid;
switch(pid = fork()){
case -1:
fatal("fork");
case 0:
exec(file, &file);
snprint(buf, sizeof buf, "can't exec %s", file);
fatal(buf);
default:
while((w = wait()) != nil)
if(w->pid == pid)
break;
if(w == nil){
snprint(buf, sizeof buf, "wait returned nil running %s", file);
free(w);
fatal(buf);
}
free(w);
}
}
int
writefile(char *name, char *buf, int len)
{
@ -104,12 +70,12 @@ writefile(char *name, char *buf, int len)
}
void
setenv(char *name, char *val)
setenv(char *name, char *val, int ec)
{
int f;
char ename[64];
snprint(ename, sizeof ename, "#e/%s", name);
snprint(ename, sizeof ename, "#e%s/%s", ec ? "c" : "", name);
f = create(ename, 1, 0666);
if(f < 0){
fprint(2, "create %s: %r\n", ename);
@ -142,41 +108,3 @@ srvcreate(char *name, int fd)
close(f);
}
void
catchint(void *a, char *note)
{
USED(a);
if(strcmp(note, "alarm") == 0)
noted(NCONT);
noted(NDFLT);
}
int
outin(char *prompt, char *def, int len)
{
int n;
char buf[256];
if(len >= sizeof buf)
len = sizeof(buf)-1;
if(cpuflag){
notify(catchint);
alarm(15*1000);
}
print("%s[%s]: ", prompt, *def ? def : "no default");
memset(buf, 0, sizeof buf);
n = read(0, buf, len);
if(cpuflag){
alarm(0);
notify(0);
}
if(n < 0)
return 1;
if(n > 1){
buf[n-1] = 0;
strcpy(def, buf);
}
return n;
}

View file

@ -5,43 +5,20 @@
#include "../boot/boot.h"
char cputype[64];
char sys[2*64];
char reply[256];
int printcol;
int mflag;
int fflag;
int kflag;
char *bargv[Nbarg];
int bargc;
static void swapproc(void);
static Method *rootserver(char*);
static void usbinit(void);
static void kbmap(void);
void
boot(int argc, char *argv[])
{
int fd, afd;
Method *mp;
char *cmd, cmdbuf[64], *iargv[16];
char rootbuf[64];
int islocal, ishybrid;
char *rp, *rsp;
int iargc, n;
char buf[32];
AuthInfo *ai;
Waitmsg *w;
int pid, i;
fmtinstall('r', errfmt);
/*
* we should inherit the standard fds all referring to /dev/cons,
* but we're being paranoid.
*/
close(0);
close(1);
close(2);
bind("#c", "/dev", MBEFORE);
open("/dev/cons", OREAD);
open("/dev/cons", OWRITE);
@ -53,12 +30,13 @@ boot(int argc, char *argv[])
bind("#ec", "/env", MREPL);
bind("#e", "/env", MBEFORE|MCREATE);
bind("#s", "/srv", MREPL|MCREATE);
#ifdef DEBUG
print("argc=%d\n", argc);
for(fd = 0; fd < argc; fd++)
print("%#p %s ", argv[fd], argv[fd]);
print("\n");
#endif DEBUG
if(Debug){
print("argc=%d\n", argc);
for(i = 0; i < argc; i++)
print("%lux %s ", (ulong)argv[i], argv[i]);
print("\n");
}
ARGBEGIN{
case 'k':
@ -73,281 +51,35 @@ boot(int argc, char *argv[])
}ARGEND
readfile("#e/cputype", cputype, sizeof(cputype));
/*
* set up usb keyboard, mouse and disk, if any.
*/
usbinit();
/*
* pick a method and initialize it
*/
if(method[0].name == nil)
fatal("no boot methods");
mp = rootserver(argc ? *argv : 0);
(*mp->config)(mp);
islocal = strcmp(mp->name, "local") == 0;
ishybrid = strcmp(mp->name, "hybrid") == 0;
/*
* load keymap if it's there.
*/
kbmap();
/*
* authentication agent
*/
authentication(cpuflag);
/*
* connect to the root file system
*/
fd = (*mp->connect)();
if(fd < 0)
fatal("can't connect to file server");
if(getenv("srvold9p"))
fd = old9p(fd);
if(!islocal && !ishybrid){
if(cfs)
fd = (*cfs)(fd);
}
print("version...");
buf[0] = '\0';
n = fversion(fd, 0, buf, sizeof buf);
if(n < 0)
fatal("can't init 9P");
srvcreate("boot", fd);
/*
* create the name space, mount the root fs
*/
if(bind("/", "/", MREPL) < 0)
fatal("bind /");
rp = getenv("rootspec");
if(rp == nil)
rp = "";
setenv("bootdisk", bootdisk, 0);
afd = fauth(fd, rp);
if(afd >= 0){
ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
if(ai == nil)
print("authentication failed (%r), trying mount anyways\n");
}
if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
fatal("mount /");
rsp = rp;
rp = getenv("rootdir");
if(rp == nil)
rp = rootdir;
if(bind(rp, "/", MAFTER|MCREATE) < 0){
if(strncmp(rp, "/root", 5) == 0){
fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
fatal("second bind /");
}
snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
rp = rootbuf;
if(bind(rp, "/", MAFTER|MCREATE) < 0){
fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
if(strcmp(rootbuf, "/root//plan9") == 0){
fprint(2, "**** warning: remove rootdir=/plan9 entry from plan9.ini\n");
rp = "/root";
if(bind(rp, "/", MAFTER|MCREATE) < 0)
fatal("second bind /");
}else
fatal("second bind /");
}
}
close(fd);
setenv("rootdir", rp);
/* setup the boot namespace */
run("/boot/mntgen", "-s", "slash", "/mnt", nil);
run("/boot/bzfs", "-f", "/boot/rootfs.bz2", "-m", "/mnt/broot", nil);
bind("/mnt/broot", "/", MAFTER);
bind("/386/bin", "/bin", MAFTER);
bind("/rc/bin", "/bin", MAFTER);
bind("/boot", "/bin", MAFTER);
settime(islocal, afd, rsp);
if(afd > 0)
close(afd);
swapproc();
cmd = getenv("init");
if(cmd == nil){
sprint(cmdbuf, "/%s/init -%s%s", cputype,
cpuflag ? "c" : "t", mflag ? "m" : "");
cmd = cmdbuf;
}
iargc = tokenize(cmd, iargv, nelem(iargv)-1);
cmd = iargv[0];
/* make iargv[0] basename(iargv[0]) */
if(iargv[0] = strrchr(iargv[0], '/'))
iargv[0]++;
else
iargv[0] = cmd;
iargv[iargc] = nil;
exec(cmd, iargv);
fatal(cmd);
}
static Method*
findmethod(char *a)
{
Method *mp;
int i, j;
char *cp;
if((i = strlen(a)) == 0)
return nil;
cp = strchr(a, '!');
if(cp)
i = cp - a;
for(mp = method; mp->name; mp++){
j = strlen(mp->name);
if(j > i)
j = i;
if(strncmp(a, mp->name, j) == 0)
break;
}
if(mp->name)
return mp;
return nil;
}
/*
* ask user from whence cometh the root file system
*/
static Method*
rootserver(char *arg)
{
char prompt[256];
Method *mp;
char *cp;
int n;
/* look for required reply */
readfile("#e/nobootprompt", reply, sizeof(reply));
if(reply[0]){
mp = findmethod(reply);
if(mp)
goto HaveMethod;
print("boot method %s not found\n", reply);
reply[0] = 0;
}
/* make list of methods */
mp = method;
n = sprint(prompt, "root is from (%s", mp->name);
for(mp++; mp->name; mp++)
n += sprint(prompt+n, ", %s", mp->name);
sprint(prompt+n, ")");
/* create default reply */
readfile("#e/bootargs", reply, sizeof(reply));
if(reply[0] == 0 && arg != 0)
strcpy(reply, arg);
if(reply[0]){
mp = findmethod(reply);
if(mp == 0)
reply[0] = 0;
}
if(reply[0] == 0)
strcpy(reply, method->name);
/* parse replies */
do{
outin(prompt, reply, sizeof(reply));
mp = findmethod(reply);
}while(mp == nil);
HaveMethod:
bargc = tokenize(reply, bargv, Nbarg-2);
bargv[bargc] = nil;
cp = strchr(reply, '!');
if(cp)
strcpy(sys, cp+1);
return mp;
}
static void
swapproc(void)
{
int fd;
fd = open("#c/swap", OWRITE);
if(fd < 0){
warning("opening #c/swap");
return;
}
if(write(fd, "start", 5) <= 0)
warning("starting swap kproc");
close(fd);
}
int
old9p(int fd)
{
int p[2];
if(pipe(p) < 0)
fatal("pipe");
print("srvold9p...");
switch(fork()) {
switch(pid = rfork(RFFDG|RFREND|RFPROC)){
case -1:
fatal("rfork srvold9p");
fatal("fork error");
case 0:
dup(fd, 1);
close(fd);
dup(p[0], 0);
close(p[0]);
close(p[1]);
execl("/srvold9p", "srvold9p", "-s", 0);
fatal("exec srvold9p");
setenv("cpuflag", cpuflag ? "1" : "0", 0);
run("/bin/rc", "/rc/bin/bootrc", nil);
break;
default:
close(fd);
close(p[0]);
}
return p[1];
}
static void
usbinit(void)
{
static char usbd[] = "/boot/usbd";
if(access("#u/usb/ctl", 0) >= 0 && bind("#u", "/dev", MAFTER) >= 0 &&
access(usbd, AEXIST) >= 0)
run(usbd, nil);
}
static void
kbmap(void)
{
char *f;
int n, in, out;
char buf[1024];
f = getenv("kbmap");
if(f == nil)
return;
if(bind("", "/dev", MAFTER) < 0){
warning("can't bind #κ");
return;
}
in = open(f, OREAD);
if(in < 0){
warning("can't open kbd map: %r");
return;
}
out = open("/dev/kbmap", OWRITE);
if(out < 0) {
warning("can't open /dev/kbmap: %r");
close(in);
return;
}
while((n = read(in, buf, sizeof(buf))) > 0)
if(write(out, buf, n) != n){
warning("write to /dev/kbmap failed");
break;
while((w = wait()) != nil)
if(w->pid == pid)
break;
if(w == nil){
free(w);
fatal("wait error");
}
close(in);
close(out);
free(w);
break;
}
for(;;)
;
}

View file

@ -1,73 +1,18 @@
typedef struct Method Method;
struct Method
{
char *name;
void (*config)(Method*);
int (*connect)(void);
char *arg;
};
enum
{
Statsz= 256,
Nbarg= 16,
enum {
Debug = 0,
};
extern void authentication(int);
extern char* bootdisk;
extern char* rootdir;
extern int (*cfs)(int);
extern int cpuflag;
extern char cputype[];
extern int fflag;
extern int kflag;
extern Method method[];
extern void (*pword)(int, Method*);
extern char sys[];
extern uchar hostkey[];
extern uchar statbuf[Statsz];
extern int bargc;
extern char *bargv[Nbarg];
extern int pcload;
extern int (*cfs)(int);
extern int cpuflag;
extern char cputype[];
extern int fflag;
extern int kflag;
/* libc equivalent */
extern int cache(int);
extern char* checkkey(Method*, char*, char*);
extern void fatal(char*);
extern void getpasswd(char*, int);
extern void key(int, Method*);
extern int outin(char*, char*, int);
extern int plumb(char*, char*, int*, char*);
extern void fatal(char*);
extern int readfile(char*, char*, int);
extern long readn(int, void*, long);
extern void run(char *file, ...);
extern int sendmsg(int, char*);
extern void setenv(char*, char*);
extern void settime(int, int, char*);
extern void srvcreate(char*, int);
extern void warning(char*);
extern void run(char*, ...);
extern void setenv(char*, char*, int);
extern int writefile(char*, char*, int);
extern void boot(int, char **);
extern void doauthenticate(int, Method*);
extern int old9p(int);
extern int parsefields(char*, char**, int, char*);
/* methods */
extern void configtcp(Method*);
extern int connecttcp(void);
extern void configlocal(Method*);
extern int connectlocal(void);
extern void configsac(Method*);
extern int connectsac(void);
extern void configpaq(Method*);
extern int connectpaq(void);
extern void configembed(Method*);
extern int connectembed(void);
extern void configip(int, char**, int);
/* hack for passing authentication address */
extern char *authaddr;

View file

@ -1,72 +0,0 @@
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include "../boot/boot.h"
char *authaddr;
static void glenda(void);
void
authentication(int cpuflag)
{
char *s;
char *argv[16], **av;
int ac;
if(access("/boot/factotum", AEXEC) < 0){
glenda();
return;
}
/* start agent */
ac = 0;
av = argv;
av[ac++] = "factotum";
if(getenv("debugfactotum"))
av[ac++] = "-p";
s = getenv("factotumopts");
if(s != nil && *s != '\0')
av[ac++] = s;
// av[ac++] = "-d"; /* debug traces */
// av[ac++] = "-D"; /* 9p messages */
if(cpuflag)
av[ac++] = "-S";
else
av[ac++] = "-u";
av[ac++] = "-sfactotum";
if(authaddr != nil){
av[ac++] = "-a";
av[ac++] = authaddr;
}
av[ac] = 0;
switch(fork()){
case -1:
fatal("starting factotum: %r");
case 0:
exec("/boot/factotum", av);
fatal("execing /boot/factotum");
}
/* wait for agent to really be there */
while(access("/mnt/factotum", 0) < 0)
sleep(250);
}
static void
glenda(void)
{
int fd;
char *s;
s = getenv("user");
if(s == nil)
s = "glenda";
fd = open("#c/hostowner", OWRITE);
if(fd >= 0){
if(write(fd, s, strlen(s)) != strlen(s))
fprint(2, "setting #c/hostowner to %s: %r\n", s);
close(fd);
}
}

View file

@ -1,80 +0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
uchar statbuf[Statsz];
int
cache(int fd)
{
int argc, i, p[2];
char *argv[5], bd[32], buf[256], partition[64], *pp;
if(stat("/boot/cfs", statbuf, sizeof statbuf) < 0)
return fd;
*partition = 0;
bind("#S", "/dev", MAFTER);
readfile("#e/cfs", buf, sizeof(buf));
if(*buf){
argc = tokenize(buf, argv, 4);
for(i = 0; i < argc; i++){
if(strcmp(argv[i], "off") == 0)
return fd;
else if(stat(argv[i], statbuf, sizeof statbuf) >= 0){
strncpy(partition, argv[i], sizeof(partition)-1);
partition[sizeof(partition)-1] = 0;
}
}
}
if(*partition == 0){
readfile("#e/bootdisk", bd, sizeof(bd));
if(*bd){
if(pp = strchr(bd, ':'))
*pp = 0;
/* damned artificial intelligence */
i = strlen(bd);
if(strcmp("disk", &bd[i-4]) == 0)
bd[i-4] = 0;
else if(strcmp("fs", &bd[i-2]) == 0)
bd[i-2] = 0;
else if(strcmp("fossil", &bd[i-6]) == 0)
bd[i-6] = 0;
sprint(partition, "%scache", bd);
if(stat(partition, statbuf, sizeof statbuf) < 0)
*bd = 0;
}
if(*bd == 0){
sprint(partition, "%scache", bootdisk);
if(stat(partition, statbuf, sizeof statbuf) < 0)
return fd;
}
}
print("cfs...");
if(pipe(p)<0)
fatal("pipe");
switch(fork()){
case -1:
fatal("fork");
case 0:
close(p[1]);
dup(fd, 0);
close(fd);
dup(p[0], 1);
close(p[0]);
if(fflag)
execl("/boot/cfs", "bootcfs", "-rs", "-f", partition, 0);
else
execl("/boot/cfs", "bootcfs", "-s", "-f", partition, 0);
break;
default:
close(p[0]);
close(fd);
fd = p[1];
break;
}
return fd;
}

View file

@ -1,203 +0,0 @@
#include <u.h>
#include <libc.h>
#include <ip.h>
#include "boot.h"
static uchar fsip[IPaddrlen];
uchar auip[IPaddrlen];
static char mpoint[32];
static int isvalidip(uchar*);
static void netndb(char*, uchar*);
static void netenv(char*, uchar*);
void
configip(int bargc, char **bargv, int needfs)
{
Waitmsg *w;
int argc, pid;
char **arg, **argv, buf[32], *p;
fmtinstall('I', eipfmt);
fmtinstall('M', eipfmt);
fmtinstall('E', eipfmt);
arg = malloc((bargc+1) * sizeof(char*));
if(arg == nil)
fatal("%r");
memmove(arg, bargv, bargc * sizeof(char*));
arg[bargc] = 0;
argc = bargc;
argv = arg;
strcpy(mpoint, "/net");
ARGBEGIN {
case 'x':
p = ARGF();
if(p != nil)
snprint(mpoint, sizeof(mpoint), "/net%s", p);
break;
case 'g':
case 'b':
case 'h':
case 'm':
p = ARGF();
USED(p);
break;
} ARGEND;
/* bind in an ip interface */
if(bind("#I", mpoint, MAFTER) < 0)
fatal("bind #I: %r\n");
if(access("#l0", 0) == 0 && bind("#l0", mpoint, MAFTER) < 0)
print("bind #l0: %r\n");
if(access("#l1", 0) == 0 && bind("#l1", mpoint, MAFTER) < 0)
print("bind #l1: %r\n");
if(access("#l2", 0) == 0 && bind("#l2", mpoint, MAFTER) < 0)
print("bind #l2: %r\n");
if(access("#l3", 0) == 0 && bind("#l3", mpoint, MAFTER) < 0)
print("bind #l3: %r\n");
werrstr("");
/* let ipconfig configure the ip interface */
switch(pid = fork()){
case -1:
fatal("configuring ip: %r");
case 0:
exec("/boot/ipconfig", arg);
fatal("execing /ipconfig");
default:
break;
}
/* wait for ipconfig to finish */
for(;;){
w = wait();
if(w != nil && w->pid == pid){
if(w->msg[0] != 0)
fatal(w->msg);
free(w);
break;
} else if(w == nil)
fatal("configuring ip");
free(w);
}
if(!needfs)
return;
/* if we didn't get a file and auth server, query user */
netndb("fs", fsip);
if(!isvalidip(fsip))
netenv("fs", fsip);
while(!isvalidip(fsip)){
buf[0] = 0;
outin("filesystem IP address", buf, sizeof(buf));
if (parseip(fsip, buf) == -1)
fprint(2, "configip: can't parse fs ip %s\n", buf);
}
netndb("auth", auip);
if(!isvalidip(auip))
netenv("auth", auip);
while(!isvalidip(auip)){
buf[0] = 0;
outin("authentication server IP address", buf, sizeof(buf));
if (parseip(auip, buf) == -1)
fprint(2, "configip: can't parse auth ip %s\n", buf);
}
}
static void
setauthaddr(char *proto, int port)
{
char buf[128];
snprint(buf, sizeof buf, "%s!%I!%d", proto, auip, port);
authaddr = strdup(buf);
}
void
configtcp(Method*)
{
configip(bargc, bargv, 1);
setauthaddr("tcp", 567);
}
int
connecttcp(void)
{
int fd;
char buf[64];
snprint(buf, sizeof buf, "tcp!%I!564", fsip);
fd = dial(buf, 0, 0, 0);
if (fd < 0)
werrstr("dial %s: %r", buf);
return fd;
}
static int
isvalidip(uchar *ip)
{
if(ipcmp(ip, IPnoaddr) == 0)
return 0;
if(ipcmp(ip, v4prefix) == 0)
return 0;
return 1;
}
static void
netenv(char *attr, uchar *ip)
{
int fd, n;
char buf[128];
ipmove(ip, IPnoaddr);
snprint(buf, sizeof(buf), "#e/%s", attr);
fd = open(buf, OREAD);
if(fd < 0)
return;
n = read(fd, buf, sizeof(buf)-1);
if(n <= 0)
return;
buf[n] = 0;
if (parseip(ip, buf) == -1)
fprint(2, "netenv: can't parse ip %s\n", buf);
}
static void
netndb(char *attr, uchar *ip)
{
int fd, n, c;
char buf[1024];
char *p;
ipmove(ip, IPnoaddr);
snprint(buf, sizeof(buf), "%s/ndb", mpoint);
fd = open(buf, OREAD);
if(fd < 0)
return;
n = read(fd, buf, sizeof(buf)-1);
close(fd);
if(n <= 0)
return;
buf[n] = 0;
n = strlen(attr);
for(p = buf; ; p++){
p = strstr(p, attr);
if(p == nil)
break;
c = *(p-1);
if(*(p + n) == '=' && (p == buf || c == '\n' || c == ' ' || c == '\t')){
p += n+1;
if (parseip(ip, p) == -1)
fprint(2, "netndb: can't parse ip %s\n", p);
return;
}
}
return;
}

View file

@ -2,17 +2,8 @@ BOOTDIR=../boot
BOOTLIB=$BOOTDIR/libboot.a$O
BOOTFILES=\
bootauth.$O\
aux.$O\
boot.$O\
bootcache.$O\
bootip.$O\
local.$O\
embed.$O\
settime.$O\
sac.$O\
paq.$O\
printstub.$O\
$BOOTLIB(%.$O):N: %.$O

183
sys/src/9/boot/bootrc Normal file
View file

@ -0,0 +1,183 @@
# TODO
# settime
# handle rootspec
# handle rootdir
# clean rc environment before running init(8)
# kfs
# caching
rfork e
# boot methods
mlocal = (configlocal connectlocal)
mtcp = (configtcp connecttcp)
mtab = (mlocal mtcp)
config=1
connect=2
bootargs=()
. /rc/lib/conf.rc
. /rc/lib/menu.rc
. /rc/lib/local.rc
. /rc/lib/tcp.rc
cputype=`{cat '#e'/cputype}
fn fatal {
echo $*
exit $"*
}
fn must {
$* || fatal $"*^': '^$status
}
fn usbinit{
if(test -f '#u'){
bind -a '#u' /dev
# TODO: check access to /dev/usb
must usbd
}
}
fn kbmap{
if(! ~ $#kbmap 0){
bind -a '#κ' /dev
cat $kbmap > /dev/kbmap
}
}
fn readmethod{
resp=()
timeo=5
found=0
echo
echo Storage devices
for(i in /dev/sd??){
echo -n local!^$i' '
echo `{sed 's/inquiry[ ]+//g; q' $i/ctl}\
partitions: `{cat $i/ctl | grep part | awk '{print $2}'}
}
while(~ $found 0){
if(~ $#pcload 0)
echo -n 'root is from: '
if not
echo -n 'kernel is at: '
while(~ $#resp 0){
resp=`{tread $timeo}
if(! ~ $status ''){
bootconf # set configuration from file
if(! ~ $#nobootprompt 0)
bootargs=$nobootprompt
resp=$bootargs
}
if(~ $resp !rc)
rc
timeo=0
}
method=`{echo $resp | awk -F! '{print $1}'}
NF=`{echo $resp | awk -F! '{print NF}'}
for(i in `{seq 1 $#mtab}){
if(~ $mtab($i) m^$method)
found = $i
}
if(~ $found 0){
echo method $method not found
resp=()
}
}
methodarg = `{echo $resp | sed 's/^[A-Za-z]+!(.*)$/\1/'}
mp = $$mtab($found)
}
fn authentication{
# in pcload we only need to read the kernel
if(~ $pcload 1)
user=none
if(! test -x /boot/factotum){
if(~ $#user 0)
user=glenda
echo -n $user > '#c'/hostowner
}
if not{
x=(/boot/factotum -u -sfactotum)
if(~ $cpuflag 1)
x=($x -S)
if(! ~ $#authaddr 0)
x=($x -a $authaddr)
if(! ~ $#debugfactotum 0)
x=($x -p)
must $x
}
}
fn swapproc{
if(test -x '#c'/swap)
echo -n start > '#c'/swap
}
usbinit # set up usb keyboard, mouse, and disk, if any
kbmap
configlocal # add partitions and binds
readmethod
$mp($config)
switch($method){
case local
islocal=1
case hybrid
ishybrid=1
}
# authentication agent
authentication
# connect to the root file system
$mp($connect)
swapproc
mount -c '#s/boot' /root
# remove part of our temporary root
unmount /$cputype/bin /bin
/mnt/broot/$cputype/bin/unmount /rc/bin /bin
/mnt/broot/$cputype/bin/unmount /boot /bin
/mnt/broot/$cputype/bin/unmount /
if(~ $pcload 1)
/boot/echo reboot /root/$kern >/dev/reboot
# create the name space, mount the root fs
/mnt/broot/$cputype/bin/bind / /
/mnt/broot/$cputype/bin/mount -ac '#s/boot' /
# remove the remaining temporary root
/mnt/broot/$cputype/bin/unmount /mnt/broot
rootdir=/root
if(~ $#init 0){
init=/$cputype/init
if(~ $cpuflag 1)
init=($init -c)
if not
init=($init -t)
# TODO handle mflag
}
$init

50
sys/src/9/boot/conf.rc Normal file
View file

@ -0,0 +1,50 @@
#!/bin/rc
mounted=0
found=0
fn confmount{
part=`{echo $1 | sed 's!^.*/!!g; s!''$!!g'}
switch($part){
case dos
mprog=dossrv
case 9fat
mprog=dossrv
case fd?disk
mprog=dossrv
case data
mprog=9660srv
case *
mprog=0
mounted=0
}
if(! ~ $mprog 0){
$mprog -f $1 conf >/dev/null >[2=1]
mount /srv/conf /mnt/conf
mounted=1
}
}
fn findconf{
# search cd/dvd drives first
for(d in $cddevs /dev/sd* /dev/fd*disk)
for(p in `{ls $d}){
if(~ $found 0){
confmount $p
if(test -e /mnt/conf/plan9.ini)
found=1
if(test $mounted -eq 1 -a $found -eq 0){
unmount /mnt/conf
rm /srv/conf
}
}
}
}
fn bootconf{
findconf
if(~ $found 1)
parseconf
}

View file

@ -1,126 +0,0 @@
#include <u.h>
#include <libc.h>
#include <auth.h>
#include "../boot/boot.h"
static char *pbmsg = "AS protocol botch";
static char *ccmsg = "can't connect to AS";
long
readn(int fd, void *buf, long len)
{
int m, n;
char *p;
p = buf;
for(n = 0; n < len; n += m){
m = read(fd, p+n, len-n);
if(m <= 0)
return -1;
}
return n;
}
static char*
fromauth(Method *mp, char *trbuf, char *tbuf)
{
int afd;
char t;
char *msg;
static char error[2*ERRMAX];
if(mp->auth == 0)
fatal("no method for accessing auth server");
afd = (*mp->auth)();
if(afd < 0) {
sprint(error, "%s: %r", ccmsg);
return error;
}
if(write(afd, trbuf, TICKREQLEN) < 0 || read(afd, &t, 1) != 1){
close(afd);
sprint(error, "%s: %r", pbmsg);
return error;
}
switch(t){
case AuthOK:
msg = 0;
if(readn(afd, tbuf, 2*TICKETLEN) < 0) {
sprint(error, "%s: %r", pbmsg);
msg = error;
}
break;
case AuthErr:
if(readn(afd, error, ERRMAX) < 0) {
sprint(error, "%s: %r", pbmsg);
msg = error;
}
else {
error[ERRMAX-1] = 0;
msg = error;
}
break;
default:
msg = pbmsg;
break;
}
close(afd);
return msg;
}
void
doauthenticate(int fd, Method *mp)
{
char *msg;
char trbuf[TICKREQLEN];
char tbuf[2*TICKETLEN];
print("session...");
if(fsession(fd, trbuf, sizeof trbuf) < 0)
fatal("session command failed");
/* no authentication required? */
memset(tbuf, 0, 2*TICKETLEN);
if(trbuf[0] == 0)
return;
/* try getting to an auth server */
print("getting ticket...");
msg = fromauth(mp, trbuf, tbuf);
print("authenticating...");
if(msg == 0)
if(fauth(fd, tbuf) >= 0)
return;
/* didn't work, go for the security hole */
fprint(2, "no authentication server (%s), using your key as server key\n", msg);
}
char*
checkkey(Method *mp, char *name, char *key)
{
char *msg;
Ticketreq tr;
Ticket t;
char trbuf[TICKREQLEN];
char tbuf[TICKETLEN];
memset(&tr, 0, sizeof tr);
tr.type = AuthTreq;
strcpy(tr.authid, name);
strcpy(tr.hostid, name);
strcpy(tr.uid, name);
convTR2M(&tr, trbuf);
msg = fromauth(mp, trbuf, tbuf);
if(msg == ccmsg){
fprint(2, "boot: can't contact auth server, passwd unchecked\n");
return 0;
}
if(msg)
return msg;
convM2T(tbuf, &t, key);
if(t.num == AuthTc && strcmp(name, t.cuid)==0)
return 0;
return "no match";
}

View file

@ -1,74 +0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
static char *paqfile;
void
configembed(Method *m)
{
if(*sys == '/' || *sys == '#'){
/*
* if the user specifies the disk in the boot cmd or
* 'root is from' prompt, use it
*/
paqfile = sys;
} else if(m->arg){
/*
* a default is supplied when the kernel is made
*/
paqfile = m->arg;
}
}
int
connectembed(void)
{
int i, p[2];
Dir *dir;
char **arg, **argp;
dir = dirstat("/boot/paqfs");
if(dir == nil)
return -1;
free(dir);
dir = dirstat(paqfile);
if(dir == nil || dir->mode & DMDIR)
return -1;
free(dir);
print("paqfs...");
if(bind("#c", "/dev", MREPL) < 0)
fatal("bind #c");
if(bind("#p", "/proc", MREPL) < 0)
fatal("bind #p");
if(pipe(p)<0)
fatal("pipe");
switch(fork()){
case -1:
fatal("fork");
case 0:
arg = malloc((bargc+5)*sizeof(char*));
argp = arg;
*argp++ = "/boot/paqfs";
*argp++ = "-iv";
*argp++ = paqfile;
for(i=1; i<bargc; i++)
*argp++ = bargv[i];
*argp = 0;
dup(p[0], 0);
dup(p[1], 1);
close(p[0]);
close(p[1]);
exec("/boot/paqfs", arg);
fatal("can't exec paqfs");
default:
break;
}
waitpid();
close(p[1]);
return p[0];
}

View file

@ -1,43 +0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
void
getpasswd(char *p, int len)
{
char c;
int i, n, fd;
fd = open("#c/consctl", OWRITE);
if(fd < 0)
fatal("can't open consctl; please reboot");
write(fd, "rawon", 5);
Prompt:
print("password: ");
n = 0;
for(;;){
do{
i = read(0, &c, 1);
if(i < 0)
fatal("can't read cons; please reboot");
}while(i == 0);
switch(c){
case '\n':
p[n] = '\0';
close(fd);
print("\n");
return;
case '\b':
if(n > 0)
n--;
break;
case 'u' - 'a' + 1: /* cntrl-u */
print("\n");
goto Prompt;
default:
if(n < len - 1)
p[n++] = c;
break;
}
}
}

View file

@ -1,275 +0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
static char diskname[64];
static char *disk;
static char **args;
void
configlocal(Method *mp)
{
char *p;
int n;
if(*sys == '/' || *sys == '#'){
/*
* if the user specifies the disk in the boot cmd or
* 'root is from' prompt, use it
*/
disk = sys;
} else if(strncmp(argv0, "dksc(0,", 7) == 0){
/*
* on many mips arg0 of the boot command specifies the
* scsi logical unit number
*/
p = strchr(argv0, ',');
n = strtoul(p+1, 0, 10);
sprint(diskname, "#w%d/sd%dfs", n, n);
disk = diskname;
} else if(mp->arg){
/*
* a default is supplied when the kernel is made
*/
disk = mp->arg;
} else if(*bootdisk){
/*
* an environment variable from a pc's plan9.ini or
* from the mips nvram or generated by the kernel
* is the last resort.
*/
disk = bootdisk;
}
/* if we've decided on one, pass it on to all programs */
if(disk)
setenv("bootdisk", disk);
USED(mp);
}
int
connectlocalkfs(void)
{
int i, pid, fd, p[2];
char partition[64];
char *dev;
char **arg, **argp;
Dir *d;
if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
return -1;
dev = disk ? disk : bootdisk;
snprint(partition, sizeof partition, "%sfs", dev);
fd = open(partition, OREAD);
if(fd < 0){
strcpy(partition, dev);
fd = open(partition, OREAD);
if(fd < 0)
return -1;
}
/*
* can't do this check -- might be some other server posing as kfs.
*
memset(buf, 0, sizeof buf);
pread(fd, buf, 512, 0);
close(fd);
if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
if(strstr(partition, "/fs"))
print("no kfs file system found on %s\n", partition);
return -1;
}
*
*/
d = dirfstat(fd);
close(fd);
if(d == nil)
return -1;
if(d->mode&DMDIR){
free(d);
return -1;
}
free(d);
print("kfs...");
if(pipe(p)<0)
fatal("pipe");
switch(pid = fork()){
case -1:
fatal("fork");
case 0:
arg = malloc((bargc+5)*sizeof(char*));
argp = arg;
*argp++ = "kfs";
*argp++ = "-f";
*argp++ = partition;
*argp++ = "-s";
for(i=1; i<bargc; i++)
*argp++ = bargv[i];
*argp = 0;
dup(p[0], 0);
dup(p[1], 1);
close(p[0]);
close(p[1]);
exec("/boot/kfs", arg);
fatal("can't exec kfs");
default:
break;
}
for(;;){
if((i = waitpid()) == -1)
fatal("waitpid for kfs failed");
if(i == pid)
break;
}
close(p[1]);
return p[0];
}
void
run(char *file, ...)
{
int i, pid;
switch(pid = fork()){
case -1:
fatal("fork");
case 0:
exec(file, &file);
fatal(smprint("can't exec %s: %r", file));
default:
while ((i = waitpid()) != pid && i != -1)
;
if(i == -1)
fatal(smprint("wait failed running %s", file));
}
}
static int
print1(int fd, char *s)
{
return write(fd, s, strlen(s));
}
void
configloopback(void)
{
int fd;
if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
bind("#I", "/net", MAFTER);
if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
fatal("open /net/ipifc/clone for loopback");
}
if(print1(fd, "bind loopback /dev/null") < 0
|| print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
fatal("write /net/ipifc/clone for loopback");
}
int
connectlocalfossil(void)
{
int fd;
char *venti, *f[32], *p;
int nf;
char partition[128], buf[512];
char *dev;
if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
return -1;
/* look for fossil partition */
dev = disk ? disk : bootdisk;
snprint(partition, sizeof partition, "%sfossil", dev);
fd = open(partition, OREAD);
if(fd < 0){
strcpy(partition, dev);
fd = open(partition, OREAD);
if(fd < 0)
return -1;
}
memset(buf, 0, sizeof buf);
pread(fd, buf, 512, 127*1024);
close(fd);
if(memcmp(buf, "fossil config\n", 14) != 0){
if(strstr(partition, "/fossil"))
print("no fossil config found on %s\n", partition);
return -1;
}
settime(1, -1, nil);
/* make venti available */
if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
if((fd = open(f[0], OREAD)) >= 0){
print("venti...");
memset(buf, 0, sizeof buf);
pread(fd, buf, 512, 248*1024);
close(fd);
if(memcmp(buf, "venti config\n", 13) != 0){
print("no venti config found on %s\n", f[0]);
return -1;
}
if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
print("/boot/venti does not exist\n");
return -1;
}
switch(nf){
case 1:
f[1] = "tcp!127.1!17034";
case 2:
f[2] = "tcp!127.1!8000";
}
configloopback();
run("/boot/venti", "-c", f[0], "-a", f[1], "-h", f[2], 0);
/*
* If the announce address is tcp!*!foo, then set
* $venti to tcp!127.1!foo instead, which is actually dialable.
*/
if((p = strstr(f[1], "!*!")) != 0){
*p = 0;
snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
f[1] = buf;
}
setenv("venti", f[1]);
}else{
/* set up the network so we can talk to the venti server */
/* this is such a crock. */
configip(nf, f, 0);
setenv("venti", f[0]);
}
}
/* start fossil */
print("fossil(%s)...", partition);
run("/boot/fossil", "-f", partition, "-c", "srv -A fboot", "-c", "srv -p fscons", 0);
fd = open("#s/fboot", ORDWR);
if(fd < 0){
print("open #s/fboot: %r\n");
return -1;
}
remove("#s/fboot"); /* we'll repost as #s/boot */
return fd;
}
int
connectlocal(void)
{
int fd;
if(bind("#c", "/dev", MREPL) < 0)
fatal("bind #c");
if(bind("#p", "/proc", MREPL) < 0)
fatal("bind #p");
bind("#S", "/dev", MAFTER);
bind("#k", "/dev", MAFTER);
bind("", "/dev", MAFTER);
if((fd = connectlocalfossil()) < 0)
if((fd = connectlocalkfs()) < 0)
return -1;
return fd;
}

72
sys/src/9/boot/local.rc Normal file
View file

@ -0,0 +1,72 @@
#!/bin/rc
cddevs=()
# fill cddevs with cd or dvd devices
fn findcds{
for(dev in /dev/sd*){
x=`{sed '/([Cc][Dd]|[Dd][Vv][Dd])/!d' $dev/ctl >[2]/dev/null}
if(! ~ $#x 0)
cddevs=($cddevs $dev)
}
}
fn configlocal{
disk=`{echo $methodarg | sed 's,(.*)!.*,\1,g'}
fstype=`{echo $disk | sed 's,.*/(.*)$,\1,g'}
disk=`{echo $disk | sed 's,(.*)/.*$,\1,'}
if(~ $pcload 1){
kern=`{echo $methodarg | sed 's,.*!(.*)$,\1,g'}
# for now we only allow kernels in the same dev/part of $methodargs
if(~ $#kern 0 || ! ~ $#bootfile 0)
kern=`{echo $bootfile | sed 's,.*!(.*)$,\1,g'}
}
bind -a '#c' /dev >/dev/null >[2=1]
bind '#p' /proc >[2=1] >/dev/null >[2=1]
bind -a '#S' /dev >/dev/null >[2=1]
bind -a '#f' /dev >/dev/null >[2=1]
bind -a '#k' /dev >/dev/null >[2=1]
bind -a '#æ' /dev >/dev/null >[2=1]
diskparts
findcds
}
fn connectlocal{
switch($fstype){
case fossil
connectlocalfossil
case fs
connectlocalkfs
case data
# test for cd/dvd
x=`{sed '/([Cc][Dd]|[Dd][Vv][Dd])/!d' $disk^/ctl}
if(! ~ $#x 0)
must 9660srv -f $disk^/$fstype boot >/dev/null >[2=1]
case *
fatal unknown partition $fstype
}
}
fn connectlocalfossil{
if(! test -x /bin/fossil/fossil){
echo no fossil
exit nofossil
}
partition=$disk^/$fstype
# settime(1, -1, nil)
# make venti available
# start fossil
echo 'fossil('$partition')...'
must fossil/fossil -f $partition -c 'srv -A boot' -c 'srv -p fscons'
}

134
sys/src/9/boot/menu.rc Normal file
View file

@ -0,0 +1,134 @@
#!/bin/rc
conffile=/mnt/conf/plan9.ini
items=()
fn menuitems{
oifs=$ifs
ifs='
'
# get menu items and save them in the form 'item\tstring'
x=(`{awk -F'\n' '
$0 ~ /\[menu\]/ {
FS="[= ]"
for(nitem=1;;nitem++){
getline
if(match($0, /\[/)) # if we entered a block, we are done
break
sub(/\,/, "") # remove comma
if(match($0, /^#/)) # comments
continue
if(match($0, /^$/)) # empty line
continue
printf("%s\t\" %d. ", $2, nitem)
for(i=3; i <= NF; i++)
printf("%s ", $i)
printf("\"\t\n")
}
}
' $conffile})
ifs=' '
for(itemline in $x){
# separate item from string
item=`{echo $itemline(1)}
# $menuitemtext holds the string for the item
$item(1)^text=$item(2)
items=($items $item(1))
}
if(! ~ $#items 0){
echo 'Plan 9 Startup Menu:'
echo '--------------------'
}
ifs=$oifs
}
# load block definitions
fn menublock{
for(i in `{
awk -F'\n' -v item'='`{echo '['$1']' | sed 's/ //g'} '
{
# find menuitem block
if(index($0, item)){
for(;;){
if(getline <= 0)
break
if(match($0, /\[/)) # entered a block, we are done
break
if(match($0, /^$/))
continue
# skip comments, quote kernel devices
if(index($0, "#") == 1)
continue
else
gsub("#", "''#''")
printf("%s\n", $1)
}
}
}' $conffile}){
name=`{echo $i | awk -F'=' '{print $1}'}
val=`{echo $i | awk -F'=' '{print $2}'}
# a name beginning with * denotes
# a kernel variable, save to #ec
v0=`{echo $i | sed 's/(\*).*/\1/'}
if(~ $v0 '*'){
bind -bc '#ec' /env
eval $name'='$val
unmount '#ec' /env
}
if not
eval $name'='$val
}
}
fn freevars{
for(i in `{
awk -F'\n' '{
if(match($0, /\[/)) # entered a block, we are done
exit
if(match($0, /^$/))
exit
# skip comments, quote kernel devices
if(index($0, "#") == 1)
exit
else
gsub("#", "''#''")
printf("%s\n", $1)
}' $conffile}){
# a name beginning with * denotes
# a kernel variable, save to #ec
val=`{echo $i | sed 's/(\*).*/\1/'}
if(~ $val '*'){
bind -bc '#ec' /env
eval $i
unmount '#ec' /env
}
if not eval $i
}
}
fn parseconf{
opt=0
if(test -f $conffile){
freevars
menuitems
menublock 'common'
if(! ~ $#items 0){
while(test $opt -lt 1 || test $opt -gt $#items){
for(item in $items)
echo -n $`{echo $item^text} | sed 's/"//g'
echo -n ' Selection: '
opt=`{read}
if(test $opt -ge 1 && test $opt -le $#items)
menublock $items($opt)
}
}
}
}

View file

@ -12,53 +12,6 @@ cat <<'---'
#include <libc.h>
#include "../boot/boot.h"
Method method[]={
---
#
# configure all remote methods, i.e. all methods in the 'boot' section
#
# EXAMPLE
# boot
# incon
# 9600
# 19200
#
../port/mkextract boot 0 $* | awk '{
printf " { \"" "" $1 "\", "\
"config" $1 ", "\
"connect" $1 ", "
print fieldn(2) " },"
}
func fieldn(n, s,i)
{
s = $0
while (n > 1) {
sub(/^[ \t]*/, "", s)
if (substr(s, 1, 1) == "\"") {
sub(/^"[^\"]*"/, "", s)
} else {
sub(/^[^ \t]*/, "", s)
}
n--
}
sub(/^[ \t]*/, "", s)
if (substr(s, 1, 1) == "\"") {
i = index(substr(s, 2), "\"")
if (i > 0)
return substr(s, 1, i+1)
else
return s
} else {
sub(/[ \t].*/, "", s)
return s
}
}'
cat <<'---'
{ 0 },
};
---
awk '

View file

@ -1,52 +0,0 @@
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include "../boot/boot.h"
static Fcall hdr;
static void
rpc(int fd, int type)
{
int n, l;
char buf[128], *p;
hdr.type = type;
hdr.tag = NOTAG;
n = convS2M(&hdr, buf);
if(write(fd, buf, n) != n)
fatal("write rpc");
print("...");
p = buf;
l = 0;
while(l < 3) {
n = read(fd, p, 3);
if(n <= 0)
fatal("read rpc");
if(n == 2 && l == 0 && buf[0] == 'O' && buf[1] == 'K')
continue;
p += n;
l += n;
}
if(convM2S(buf, &hdr, n) == 0){
print("%ux %ux %ux\n", buf[0], buf[1], buf[2]);
fatal("rpc format");
}
if(hdr.tag != NOTAG)
fatal("rpc tag not NOTAG");
if(hdr.type == Rerror){
print("error %s;", hdr.ename);
fatal("remote error");
}
if(hdr.type != type+1)
fatal("not reply");
}
void
nop(int fd)
{
print("nop");
rpc(fd, Tnop);
}

View file

@ -1,67 +0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
char *fparts[] =
{
"add bootldr 0x0000000 0x0040000",
"add params 0x0040000 0x0080000",
"add kernel 0x0080000 0x0140000",
"add user 0x0140000 0x0200000",
"add ramdisk 0x0200000 0x0600000",
};
void
configpaq(Method*)
{
int fd;
int i;
if(bind("#F", "/dev", MAFTER) < 0)
fatal("bind #c");
if(bind("#p", "/proc", MREPL) < 0)
fatal("bind #p");
fd = open("/dev/flash/flashctl", OWRITE);
if(fd < 0)
fatal("opening flashctl");
for(i = 0; i < nelem(fparts); i++)
if(fprint(fd, fparts[i]) < 0)
fatal(fparts[i]);
close(fd);
}
int
connectpaq(void)
{
int p[2];
char **arg, **argp;
print("paq...");
if(pipe(p)<0)
fatal("pipe");
switch(fork()){
case -1:
fatal("fork");
case 0:
arg = malloc(10*sizeof(char*));
argp = arg;
*argp++ = "paqfs";
*argp++ = "-v";
*argp++ = "-i";
*argp++ = "/dev/flash/ramdisk";
*argp = 0;
dup(p[0], 0);
dup(p[1], 1);
close(p[0]);
close(p[1]);
exec("/boot/paqfs", arg);
fatal("can't exec paqfs");
default:
break;
}
waitpid();
close(p[1]);
return p[0];
}

View file

@ -1,50 +0,0 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
/*
* HACK - take over from boot since file system is not
* available on a pipe
*/
void
configsac(Method *mp)
{
int fd;
char cmd[64];
USED(mp);
/*
* create the name space, mount the root fs
*/
if(bind("/", "/", MREPL) < 0)
fatal("bind /");
if(bind("#C", "/", MAFTER) < 0)
fatal("bind /");
/* fixed sysname - enables correct namespace file */
fd = open("#c/sysname", OWRITE);
if(fd < 0)
fatal("open sysname");
write(fd, "brick", 5);
close(fd);
fd = open("#c/hostowner", OWRITE);
if(fd < 0)
fatal("open sysname");
write(fd, "brick", 5);
close(fd);
sprint(cmd, "/%s/init", cputype);
print("starting %s\n", cmd);
execl(cmd, "init", "-c", 0);
fatal(cmd);
}
int
connectsac(void)
{
/* does not get here */
return -1;
}

View file

@ -1,149 +0,0 @@
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include "../boot/boot.h"
static long lusertime(char*);
char *timeserver = "#s/boot";
void
settime(int islocal, int afd, char *rp)
{
int n, f;
int timeset;
Dir dir[2];
char timebuf[64];
print("time...");
timeset = 0;
if(islocal){
/*
* set the time from the real time clock
*/
f = open("#r/rtc", ORDWR);
if(f >= 0){
if((n = read(f, timebuf, sizeof(timebuf)-1)) > 0){
timebuf[n] = '\0';
timeset = 1;
}
close(f);
}else do{
strcpy(timebuf, "yymmddhhmm[ss]");
outin("\ndate/time ", timebuf, sizeof(timebuf));
}while((timeset=lusertime(timebuf)) <= 0);
}
if(timeset == 0){
/*
* set the time from the access time of the root
*/
f = open(timeserver, ORDWR);
if(f < 0)
return;
if(mount(f, afd, "/tmp", MREPL, rp) < 0){
warning("settime mount");
close(f);
return;
}
close(f);
if(stat("/tmp", statbuf, sizeof statbuf) < 0)
fatal("stat");
convM2D(statbuf, sizeof statbuf, &dir[0], (char*)&dir[1]);
sprint(timebuf, "%ld", dir[0].atime);
unmount(0, "/tmp");
}
f = open("#c/time", OWRITE);
if(write(f, timebuf, strlen(timebuf)) < 0)
warning("can't set #c/time");
close(f);
print("\n");
}
#define SEC2MIN 60L
#define SEC2HOUR (60L*SEC2MIN)
#define SEC2DAY (24L*SEC2HOUR)
int
g2(char **pp)
{
int v;
v = 10*((*pp)[0]-'0') + (*pp)[1]-'0';
*pp += 2;
return v;
}
/*
* days per month plus days/year
*/
static int dmsize[] =
{
365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
static int ldmsize[] =
{
366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
/*
* return the days/month for the given year
*/
static int *
yrsize(int y)
{
if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
return ldmsize;
else
return dmsize;
}
/*
* compute seconds since Jan 1 1970
*/
static long
lusertime(char *argbuf)
{
char *buf;
ulong secs;
int i, y, m;
int *d2m;
buf = argbuf;
i = strlen(buf);
if(i != 10 && i != 12)
return -1;
secs = 0;
y = g2(&buf);
m = g2(&buf);
if(y < 70)
y += 2000;
else
y += 1900;
/*
* seconds per year
*/
for(i = 1970; i < y; i++){
d2m = yrsize(i);
secs += d2m[0] * SEC2DAY;
}
/*
* seconds per month
*/
d2m = yrsize(y);
for(i = 1; i < m; i++)
secs += d2m[i] * SEC2DAY;
secs += (g2(&buf)-1) * SEC2DAY;
secs += g2(&buf) * SEC2HOUR;
secs += g2(&buf) * SEC2MIN;
if(*buf)
secs += g2(&buf);
sprint(argbuf, "%ld", secs);
return secs;
}

61
sys/src/9/boot/tcp.rc Normal file
View file

@ -0,0 +1,61 @@
#!/bin/rc
fn isvalidip{
# TODO: more precise test
if(! ~ $#1 0 && ! test `{echo $1 | sed '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/d'})
echo -n
}
fn configtcp{
# TODO:
# should we accept a different mount point?
# should we add more interfaces?
# bind in an ip interface
for(i in I l`{seq 0 3})
bind -a '#'$i /net >/dev/null >[2=1]
if(! test -x /bin/ip/ipconfig){
echo no ipconfig
exit noipconfig
}
ip/ipconfig # TODO: should receive args passed to boot(8)
# XXX: should configuration from file override the values from ipconfig(8)?
if(~ $#fs 0){
_fsip=`{grep fs /net/ndb | awk -F'=' '{print $2}' >/dev/null >[2=1]}
if(! ~ $#_fsip 0 && `{isvalidip $_fsip})
fsip=$_fsip
}
# if we didn't get a file and auth server from either
# the configuration file or ipconfig(8), ask the user
if(~ $#fsip 0){
while(! isvalidip $fsip){
echo -n 'filesystem IP address: '
fsip=`{read}
}
}
if(~ $#auth 0){
_authip=`{grep auth /net/ndb | awk -F'=' '{print $2}' >/dev/null >[2=1]}
if(! ~ $#_authip 0 && `{isvalidip $_authip})
authip=_authip
}
if(~ $#authip 0){
while(! isvalidip $authip){
echo -n 'authentication server IP address: '
authip=`{read}
}
}
authaddr=tcp!$authip!567 # leave this for factotum(4)
rm -f /env/_authip /env/_fsip
}
fn connecttcp{
srv -q tcp!$fsip!564 boot
}

View file

@ -1,37 +0,0 @@
#include <u.h>
#include <libc.h>
#include <auth.h>
void
usage(void)
{
fprint(2, "usage: testboot cmd args...\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int p[2];
if(argc == 1)
usage();
pipe(p);
switch(rfork(RFPROC|RFFDG|RFNAMEG)){
case -1:
sysfatal("fork: %r");
case 0:
dup(p[0], 0);
dup(p[1], 1);
exec(argv[1], argv+1);
sysfatal("exec: %r");
default:
if(amount(p[0], "/n/kremvax", MREPL, "") < 0)
sysfatal("amount: %r");
break;
}
exits(nil);
}

View file

@ -79,6 +79,9 @@ $p$CONF: $CONF.c $OBJ $LIB
$LD -o $target -T$KTZERO -l $OBJ $CONF.$O $LIB
size $target
rootfs.bz2:
rc ../port/mkbootfs
# don't strip the gzipped kernels -- too frustrating when that's all you have!
$p%.gz:D: $p%
gzip -9 <$p$stem >$p$stem.gz

View file

@ -125,6 +125,8 @@ boot boot #S/sdD0/data
bootdir
bootpccd.out boot
/386/bin/ip/ipconfig ipconfig
/386/bin/9660srv kfs
/386/bin/usb/usbd
/386/bin/auth/factotum
/386/bin/bzfs
/386/bin/echo
/386/bin/mntgen
rootfs.bz2

View file

@ -130,8 +130,8 @@ boot boot #S/sdC0/
bootdir
bootpcf.out boot
/386/bin/ip/ipconfig
/386/bin/auth/factotum
/386/bin/fossil/fossil
/386/bin/venti/venti
/386/bin/usb/usbd
/386/bin/bzfs
/386/bin/echo
/386/bin/mntgen
rootfs.bz2

View file

@ -30,7 +30,7 @@ all:V:
mk 'CONF='$i
clean:V:
rm -f *.[$OS] *.root.s *.rootc.c cfs.h fs.h init.h conf.h *.out *.m errstr.h
rm -f *.[$OS] *.root.s *.rootc.c cfs.h fs.h init.h conf.h *.out *.m errstr.h rootfs.bz2
for(i in $CONFLIST $CRAPLIST)
mk $i.clean