xref: /plan9-contrib/sys/src/9/boot/boot.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include "../boot/boot.h"
5 
6 #define DEFSYS "bootes"
7 typedef struct Net	Net;
8 typedef struct Flavor	Flavor;
9 
10 int	printcol;
11 
12 char	cputype[NAMELEN];
13 char	terminal[NAMELEN];
14 char	sys[2*NAMELEN];
15 char	username[NAMELEN];
16 char	bootfile[3*NAMELEN];
17 char	conffile[NAMELEN];
18 
19 int mflag;
20 int fflag;
21 int kflag;
22 int afd = -1;
23 
24 static void	swapproc(void);
25 static Method	*rootserver(char*);
26 
27 static int
28 rconv(void *o, Fconv *fp)
29 {
30 	char s[ERRLEN];
31 
32 	USED(o);
33 
34 	s[0] = 0;
35 	errstr(s);
36 	strconv(s, fp);
37 	return 0;
38 }
39 
40 void
41 boot(int argc, char *argv[])
42 {
43 	int fd;
44 	Method *mp;
45 	char cmd[64];
46 	char flags[6];
47 	int islocal, ishybrid;
48 	char rootdir[3*NAMELEN];
49 
50 	sleep(1000);
51 
52 	fmtinstall('r', rconv);
53 
54 	open("#c/cons", OREAD);
55 	open("#c/cons", OWRITE);
56 	open("#c/cons", OWRITE);
57 /*	print("argc=%d\n", argc);
58 	for(fd = 0; fd < argc; fd++)
59 		print("%s ", argv[fd]);
60 	print("\n");/**/
61 
62 	ARGBEGIN{
63 	case 'u':
64 		strcpy(username, ARGF());
65 		break;
66 	case 'k':
67 		kflag = 1;
68 		break;
69 	case 'm':
70 		mflag = 1;
71 		break;
72 	case 'f':
73 		fflag = 1;
74 		break;
75 	}ARGEND
76 
77 	readfile("#e/cputype", cputype, sizeof(cputype));
78 	readfile("#e/terminal", terminal, sizeof(terminal));
79 	getconffile(conffile, terminal);
80 
81 	/*
82 	 *  pick a method and initialize it
83 	 */
84 	mp = rootserver(argc ? *argv : 0);
85 	(*mp->config)(mp);
86 	islocal = strcmp(mp->name, "local") == 0;
87 	ishybrid = (mp->name[0] == 'h' || mp->name[0] == 'H') &&
88 			strcmp(&mp->name[1], "ybrid") == 0;
89 
90 	/*
91 	 *  get/set key or password
92 	 */
93 	(*pword)(islocal, mp);
94 
95 	/*
96 	 *  connect to the root file system
97 	 */
98 	fd = (*mp->connect)();
99 	if(fd < 0)
100 		fatal("can't connect to file server");
101 	if(!islocal && !ishybrid){
102 		if(cfs)
103 			fd = (*cfs)(fd);
104 		doauthenticate(fd, mp);
105 	}
106 	srvcreate("boot", fd);
107 
108 	/*
109 	 *  create the name space
110 	 */
111 	if(bind("/", "/", MREPL) < 0)
112 		fatal("bind");
113 	if(mount(fd, "/", MAFTER|MCREATE, "") < 0)
114 		fatal("mount");
115 	close(fd);
116 
117 	/*
118 	 *  hack to let us have the logical root in a
119 	 *  subdirectory - useful when we're the 'second'
120 	 *  OS along with some other like DOS.
121 	 */
122 	readfile("#e/rootdir", rootdir, sizeof(rootdir));
123 	if(rootdir[0])
124 		if(bind(rootdir, "/", MREPL|MCREATE) >= 0)
125 			bind("#/", "/", MBEFORE);
126 
127 	/*
128 	 *  if a local file server exists and it's not
129 	 *  running, start it and mount it onto /n/kfs
130 	 */
131 	if(access("#s/kfs", 0) < 0){
132 		for(mp = method; mp->name; mp++){
133 			if(strcmp(mp->name, "local") != 0)
134 				continue;
135 			(*mp->config)(mp);
136 			fd = (*mp->connect)();
137 			if(fd < 0)
138 				break;
139 			mount(fd, "/n/kfs", MAFTER|MCREATE, "") ;
140 			close(fd);
141 			break;
142 		}
143 	}
144 
145 	settime(islocal);
146 	close(afd);
147 	swapproc();
148 	remove("#e/password");
149 
150 	sprint(cmd, "/%s/init", cputype);
151 	sprint(flags, "-%s%s", cpuflag ? "c" : "t", mflag ? "m" : "");
152 	execl(cmd, "init", flags, 0);
153 	fatal(cmd);
154 }
155 
156 /*
157  *  ask user from whence cometh the root file system
158  */
159 Method*
160 rootserver(char *arg)
161 {
162 	char prompt[256];
163 	char reply[64];
164 	Method *mp;
165 	char *cp, *goodarg;
166 	int n, j;
167 
168 	goodarg = 0;
169 	mp = method;
170 	n = sprint(prompt, "root is from (%s", mp->name);
171 	if(arg && strncmp(arg, mp->name, strlen(mp->name)) == 0)
172 		goodarg = arg;
173 	for(mp++; mp->name; mp++){
174 		n += sprint(prompt+n, ", %s", mp->name);
175 		if(arg && strncmp(arg, mp->name, strlen(mp->name)) == 0)
176 			goodarg = arg;
177 	}
178 	sprint(prompt+n, ")");
179 
180 	if(goodarg)
181 		strcpy(reply, goodarg);
182 	else {
183 		strcpy(reply, method->name);
184 	}
185 	for(;;){
186 		outin(cpuflag, prompt, reply, sizeof(reply));
187 		cp = strchr(reply, '!');
188 		if(cp)
189 			j = cp - reply;
190 		else
191 			j = strlen(reply);
192 		for(mp = method; mp->name; mp++)
193 			if(strncmp(reply, mp->name, j) == 0){
194 				if(cp)
195 					strcpy(sys, cp+1);
196 				return mp;
197 			}
198 		if(mp->name == 0)
199 			continue;
200 	}
201 	return 0;		/* not reached */
202 }
203 
204 static void
205 swapproc(void)
206 {
207 	int fd;
208 
209 	fd = open("#c/swap", OWRITE);
210 	if(fd < 0){
211 		warning("opening #c/swap");
212 		return;
213 	}
214 	if(write(fd, "start", 5) <= 0)
215 		warning("starting swap kproc");
216 }
217