FreeBSD/Linux Kernel Cross Reference
sys/boot/boot.c
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include "../boot/boot.h"
6
7 char cputype[64];
8 char sys[2*64];
9 char reply[256];
10 int printcol;
11 int mflag;
12 int fflag;
13 int kflag;
14
15 char *bargv[Nbarg];
16 int bargc;
17
18 static void swapproc(void);
19 static Method *rootserver(char*);
20 static void usbinit(void);
21 static void kbmap(void);
22
23 void
24 boot(int argc, char *argv[])
25 {
26 int fd, afd;
27 Method *mp;
28 char *cmd, cmdbuf[64], *iargv[16];
29 char rootbuf[64];
30 int islocal, ishybrid;
31 char *rp, *rsp;
32 int iargc, n;
33 char buf[32];
34 AuthInfo *ai;
35
36 fmtinstall('r', errfmt);
37
38 bind("#c", "/dev", MBEFORE);
39 open("/dev/cons", OREAD);
40 open("/dev/cons", OWRITE);
41 open("/dev/cons", OWRITE);
42 /*
43 * init will reinitialize its namespace.
44 * #ec gets us plan9.ini settings (*var variables).
45 */
46 bind("#ec", "/env", MREPL);
47 bind("#e", "/env", MBEFORE|MCREATE);
48 bind("#s", "/srv", MREPL|MCREATE);
49 #ifdef DEBUG
50 print("argc=%d\n", argc);
51 for(fd = 0; fd < argc; fd++)
52 print("%lux %s ", argv[fd], argv[fd]);
53 print("\n");
54 #endif DEBUG
55
56 ARGBEGIN{
57 case 'k':
58 kflag = 1;
59 break;
60 case 'm':
61 mflag = 1;
62 break;
63 case 'f':
64 fflag = 1;
65 break;
66 }ARGEND
67
68 readfile("#e/cputype", cputype, sizeof(cputype));
69
70 /*
71 * set up usb keyboard, mouse and disk, if any.
72 */
73 usbinit();
74
75 /*
76 * pick a method and initialize it
77 */
78 if(method[0].name == nil)
79 fatal("no boot methods");
80 mp = rootserver(argc ? *argv : 0);
81 (*mp->config)(mp);
82 islocal = strcmp(mp->name, "local") == 0;
83 ishybrid = strcmp(mp->name, "hybrid") == 0;
84
85 /*
86 * load keymap if it's there.
87 */
88 kbmap();
89
90 /*
91 * authentication agent
92 */
93 authentication(cpuflag);
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(getenv("srvold9p"))
102 fd = old9p(fd);
103 if(!islocal && !ishybrid){
104 if(cfs)
105 fd = (*cfs)(fd);
106 }
107 print("version...");
108 buf[0] = '\0';
109 n = fversion(fd, 0, buf, sizeof buf);
110 if(n < 0)
111 fatal("can't init 9P");
112 srvcreate("boot", fd);
113
114 /*
115 * create the name space, mount the root fs
116 */
117 if(bind("/", "/", MREPL) < 0)
118 fatal("bind /");
119 rp = getenv("rootspec");
120 if(rp == nil)
121 rp = "";
122
123 afd = fauth(fd, rp);
124 if(afd >= 0){
125 ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
126 if(ai == nil)
127 print("authentication failed (%r), trying mount anyways\n");
128 }
129 if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
130 fatal("mount /");
131 rsp = rp;
132 rp = getenv("rootdir");
133 if(rp == nil)
134 rp = rootdir;
135 if(bind(rp, "/", MAFTER|MCREATE) < 0){
136 if(strncmp(rp, "/root", 5) == 0){
137 fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
138 fatal("second bind /");
139 }
140 snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
141 rp = rootbuf;
142 if(bind(rp, "/", MAFTER|MCREATE) < 0){
143 fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
144 if(strcmp(rootbuf, "/root//plan9") == 0){
145 fprint(2, "**** warning: remove rootdir=/plan9 entry from plan9.ini\n");
146 rp = "/root";
147 if(bind(rp, "/", MAFTER|MCREATE) < 0)
148 fatal("second bind /");
149 }else
150 fatal("second bind /");
151 }
152 }
153 close(fd);
154 setenv("rootdir", rp);
155
156 settime(islocal, afd, rsp);
157 if(afd > 0)
158 close(afd);
159 swapproc();
160
161 cmd = getenv("init");
162 if(cmd == nil){
163 sprint(cmdbuf, "/%s/init -%s%s", cputype,
164 cpuflag ? "c" : "t", mflag ? "m" : "");
165 cmd = cmdbuf;
166 }
167 iargc = tokenize(cmd, iargv, nelem(iargv)-1);
168 cmd = iargv[0];
169
170 /* make iargv[0] basename(iargv[0]) */
171 if(iargv[0] = strrchr(iargv[0], '/'))
172 iargv[0]++;
173 else
174 iargv[0] = cmd;
175
176 iargv[iargc] = nil;
177
178 exec(cmd, iargv);
179 fatal(cmd);
180 }
181
182 static Method*
183 findmethod(char *a)
184 {
185 Method *mp;
186 int i, j;
187 char *cp;
188
189 if((i = strlen(a)) == 0)
190 return nil;
191 cp = strchr(a, '!');
192 if(cp)
193 i = cp - a;
194 for(mp = method; mp->name; mp++){
195 j = strlen(mp->name);
196 if(j > i)
197 j = i;
198 if(strncmp(a, mp->name, j) == 0)
199 break;
200 }
201 if(mp->name)
202 return mp;
203 return nil;
204 }
205
206 /*
207 * ask user from whence cometh the root file system
208 */
209 static Method*
210 rootserver(char *arg)
211 {
212 char prompt[256];
213 Method *mp;
214 char *cp;
215 int n;
216
217 /* look for required reply */
218 readfile("#e/nobootprompt", reply, sizeof(reply));
219 if(reply[0]){
220 mp = findmethod(reply);
221 if(mp)
222 goto HaveMethod;
223 print("boot method %s not found\n", reply);
224 reply[0] = 0;
225 }
226
227 /* make list of methods */
228 mp = method;
229 n = sprint(prompt, "root is from (%s", mp->name);
230 for(mp++; mp->name; mp++)
231 n += sprint(prompt+n, ", %s", mp->name);
232 sprint(prompt+n, ")");
233
234 /* create default reply */
235 readfile("#e/bootargs", reply, sizeof(reply));
236 if(reply[0] == 0 && arg != 0)
237 strcpy(reply, arg);
238 if(reply[0]){
239 mp = findmethod(reply);
240 if(mp == 0)
241 reply[0] = 0;
242 }
243 if(reply[0] == 0)
244 strcpy(reply, method->name);
245
246 /* parse replies */
247 do{
248 outin(prompt, reply, sizeof(reply));
249 mp = findmethod(reply);
250 }while(mp == nil);
251
252 HaveMethod:
253 bargc = tokenize(reply, bargv, Nbarg-2);
254 bargv[bargc] = nil;
255 cp = strchr(reply, '!');
256 if(cp)
257 strcpy(sys, cp+1);
258 return mp;
259 }
260
261 static void
262 swapproc(void)
263 {
264 int fd;
265
266 fd = open("#c/swap", OWRITE);
267 if(fd < 0){
268 warning("opening #c/swap");
269 return;
270 }
271 if(write(fd, "start", 5) <= 0)
272 warning("starting swap kproc");
273 close(fd);
274 }
275
276 int
277 old9p(int fd)
278 {
279 int p[2];
280
281 if(pipe(p) < 0)
282 fatal("pipe");
283
284 print("srvold9p...");
285 switch(fork()) {
286 case -1:
287 fatal("rfork srvold9p");
288 case 0:
289 dup(fd, 1);
290 close(fd);
291 dup(p[0], 0);
292 close(p[0]);
293 close(p[1]);
294 execl("/srvold9p", "srvold9p", "-s", 0);
295 fatal("exec srvold9p");
296 default:
297 close(fd);
298 close(p[0]);
299 }
300 return p[1];
301 }
302
303 static void
304 run(char *prog, char **args)
305 {
306 int i, pid;
307
308 if (access(args[0], AEXIST) < 0)
309 return; /* avoid error messages */
310 print("%s...", prog);
311 switch(pid = fork()){
312 case -1:
313 fatal("fork");
314 case 0:
315 exec(args[0], args);
316 fatal(smprint("can't exec %s: %r", args[0]));
317 }
318 while ((i = waitpid()) != pid && i != -1)
319 ;
320 if(i == -1)
321 fatal(smprint("waitpid for %s failed", args[0]));
322 }
323
324 static void
325 usbinit(void)
326 {
327 static char *darg[] = { "/boot/usbd", nil };
328
329 if(bind("#u", "/dev", MAFTER) >= 0 && access("/dev/usb", 0) >= 0)
330 run("usbd", darg);
331 }
332
333 static void
334 kbmap(void)
335 {
336 char *f;
337 int n, in, out;
338 char buf[1024];
339
340 f = getenv("kbmap");
341 if(f == nil)
342 return;
343 if(bind("#κ", "/dev", MAFTER) < 0){
344 warning("can't bind #κ");
345 return;
346 }
347
348 in = open(f, OREAD);
349 if(in < 0){
350 warning("can't open kbd map: %r");
351 return;
352 }
353 out = open("/dev/kbmap", OWRITE);
354 if(out < 0) {
355 warning("can't open /dev/kbmap: %r");
356 close(in);
357 return;
358 }
359 while((n = read(in, buf, sizeof(buf))) > 0)
360 if(write(out, buf, n) != n){
361 warning("write to /dev/kbmap failed");
362 break;
363 }
364 close(in);
365 close(out);
366 }
Cache object: 9725c36fa9c3bc6d00fe5c84ae3180e9
|