boot.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <envvars.h>
  12. #include <auth.h>
  13. #include <9P2000.h>
  14. #include "../boot/boot.h"
  15. char cputype[64];
  16. char sys[2*64];
  17. int printcol;
  18. int mflag;
  19. int fflag;
  20. int kflag;
  21. char *bargv[Nbarg];
  22. int bargc;
  23. static Method *rootserver(char*);
  24. static void usbinit(void);
  25. static int startconsole(void);
  26. static int startcomconsole(void);
  27. static void bindBoot(void);
  28. static void unbindBoot(void);
  29. static void kbmap(void);
  30. void
  31. boot(int argc, char *argv[])
  32. {
  33. int fd, afd;
  34. Method *mp;
  35. char *cmd, cmdbuf[64], *iargv[16];
  36. char rootbuf[64];
  37. int islocal, ishybrid;
  38. char *rp, *rsp;
  39. int iargc, n;
  40. char buf[32];
  41. AuthInfo *ai;
  42. open("/dev/cons", OREAD);
  43. open("/dev/cons", OWRITE);
  44. open("/dev/cons", OWRITE);
  45. jehanne_fmtinstall('r', jehanne_errfmt);
  46. bindBoot();
  47. /*
  48. * start /dev/cons
  49. */
  50. if(readfile("#ec/bootconsole", buf, sizeof(buf)) >= 0
  51. && jehanne_strcmp("comconsole", buf) == 0){
  52. if(startcomconsole() < 0)
  53. fatal("no console found");
  54. } else if(startconsole() < 0){
  55. if(startcomconsole() < 0)
  56. fatal("no console found");
  57. }
  58. /*
  59. * init will reinitialize its namespace.
  60. * #ec gets us plan9.ini settings (*var variables).
  61. */
  62. bind("#ec", "/env", MREPL);
  63. bind("#e", "/env", MBEFORE|MCREATE);
  64. bind("#s", "/srv", MREPL|MCREATE);
  65. bind("#p", "/proc", MREPL|MCREATE);
  66. bind("#σ", "/shr", MREPL);
  67. jehanne_print("Diex vos sait! Je m'appelle Jehanne O:-)\n");
  68. #ifdef DEBUG
  69. jehanne_print("argc=%d\n", argc);
  70. for(fd = 0; fd < argc; fd++)
  71. jehanne_print("%#p %s ", argv[fd], argv[fd]);
  72. jehanne_print("\n");
  73. #endif //DEBUG
  74. ARGBEGIN{
  75. case 'k':
  76. kflag = 1;
  77. break;
  78. case 'm':
  79. mflag = 1;
  80. break;
  81. case 'f':
  82. fflag = 1;
  83. break;
  84. }ARGEND
  85. readfile("#e/" ENV_CPUTYPE, cputype, sizeof(cputype));
  86. /*
  87. * set up usb keyboard, mouse and disk, if any.
  88. */
  89. usbinit();
  90. /*
  91. * pick a method and initialize it
  92. */
  93. if(method[0].name == nil)
  94. fatal("no boot methods");
  95. mp = rootserver(argc ? *argv : 0);
  96. (*mp->config)(mp);
  97. islocal = jehanne_strcmp(mp->name, "local") == 0;
  98. ishybrid = jehanne_strcmp(mp->name, "hybrid") == 0;
  99. /*
  100. * load keymap if it is there.
  101. */
  102. kbmap();
  103. /*
  104. * authentication agent
  105. */
  106. authentication(cpuflag);
  107. jehanne_print("connect...");
  108. /*
  109. * connect to the root file system
  110. */
  111. fd = (*mp->connect)();
  112. if(fd < 0)
  113. fatal("can't connect to file server");
  114. if(!islocal && !ishybrid){
  115. if(cfs)
  116. fd = (*cfs)(fd);
  117. }
  118. jehanne_print("\n");
  119. jehanne_print("version...");
  120. buf[0] = '\0';
  121. n = fversion(fd, 0, buf, sizeof buf);
  122. if(n < 0)
  123. fatal("can't init 9P");
  124. if(jehanne_access("#s/boot", AEXIST) < 0)
  125. srvcreate("boot", fd);
  126. unbindBoot();
  127. /*
  128. * create the name space, mount the root fs
  129. */
  130. if(bind("/", "/", MREPL) < 0)
  131. fatal("bind /");
  132. rp = jehanne_getenv("rootspec");
  133. if(rp == nil)
  134. rp = "";
  135. afd = fauth(fd, rp);
  136. if(afd >= 0){
  137. ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
  138. if(ai == nil)
  139. jehanne_print("authentication failed (%r), trying mount anyways\n");
  140. }
  141. if(mount(fd, afd, "/root", MREPL|MCREATE, rp, '9') < 0)
  142. fatal("mount /");
  143. rsp = rp;
  144. rp = jehanne_getenv("rootdir");
  145. if(rp == nil)
  146. rp = rootdir;
  147. if(bind(rp, "/", MAFTER|MCREATE) < 0){
  148. if(jehanne_strncmp(rp, "/root", 5) == 0){
  149. jehanne_fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
  150. fatal("second bind /");
  151. }
  152. jehanne_snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
  153. rp = rootbuf;
  154. if(bind(rp, "/", MAFTER|MCREATE) < 0){
  155. jehanne_fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
  156. if(jehanne_strcmp(rootbuf, "/root//plan9") == 0){
  157. jehanne_fprint(2, "**** warning: remove rootdir=/plan9 entry from plan9.ini\n");
  158. rp = "/root";
  159. if(bind(rp, "/", MAFTER|MCREATE) < 0)
  160. fatal("second bind /");
  161. }else
  162. fatal("second bind /");
  163. }
  164. }
  165. close(fd);
  166. setenv("rootdir", rp);
  167. savelogs();
  168. settime(islocal, afd, rsp);
  169. if(afd > 0)
  170. close(afd);
  171. cmd = jehanne_getenv("init");
  172. if(cmd == nil){
  173. jehanne_sprint(cmdbuf, "/arch/%s/cmd/init -%s%s", cputype,
  174. cpuflag ? "c" : "t", mflag ? "m" : "");
  175. cmd = cmdbuf;
  176. }
  177. iargc = jehanne_tokenize(cmd, iargv, nelem(iargv)-1);
  178. cmd = iargv[0];
  179. /* make iargv[0] basename(iargv[0]) */
  180. if(iargv[0] = jehanne_strrchr(iargv[0], '/'))
  181. iargv[0]++;
  182. else
  183. iargv[0] = cmd;
  184. iargv[iargc] = nil;
  185. exec(cmd, (const char**)iargv);
  186. fatal(cmd);
  187. }
  188. static Method*
  189. findmethod(char *a)
  190. {
  191. Method *mp;
  192. int i, j;
  193. char *cp;
  194. if((i = jehanne_strlen(a)) == 0)
  195. return nil;
  196. cp = jehanne_strchr(a, '!');
  197. if(cp)
  198. i = cp - a;
  199. for(mp = method; mp->name; mp++){
  200. j = jehanne_strlen(mp->name);
  201. if(j > i)
  202. j = i;
  203. if(jehanne_strncmp(a, mp->name, j) == 0)
  204. break;
  205. }
  206. if(mp->name)
  207. return mp;
  208. return nil;
  209. }
  210. /*
  211. * ask user from whence cometh the root file system
  212. */
  213. static Method*
  214. rootserver(char *arg)
  215. {
  216. char prompt[256];
  217. int rc;
  218. Method *mp;
  219. char *cp;
  220. char reply[256];
  221. int n;
  222. /* look for required reply */
  223. rc = readfile("#ec/nobootprompt", reply, sizeof(reply));
  224. if(rc == 0 && reply[0]){
  225. mp = findmethod(reply);
  226. if(mp)
  227. goto HaveMethod;
  228. jehanne_print("boot method %s not found\n", reply);
  229. reply[0] = 0;
  230. }
  231. /* make list of methods */
  232. mp = method;
  233. n = jehanne_sprint(prompt, "root is from (%s", mp->name);
  234. for(mp++; mp->name; mp++)
  235. n += jehanne_sprint(prompt+n, ", %s", mp->name);
  236. jehanne_sprint(prompt+n, ")");
  237. /* create default reply */
  238. readfile("#ec/bootargs", reply, sizeof(reply));
  239. if(reply[0] == 0 && arg != 0)
  240. jehanne_strcpy(reply, arg);
  241. if(reply[0]){
  242. mp = findmethod(reply);
  243. if(mp == 0)
  244. reply[0] = 0;
  245. }
  246. if(reply[0] == 0)
  247. jehanne_strcpy(reply, method->name);
  248. /* parse replies */
  249. do{
  250. outin(prompt, reply, sizeof(reply));
  251. mp = findmethod(reply);
  252. }while(mp == nil);
  253. HaveMethod:
  254. bargc = jehanne_tokenize(reply, bargv, Nbarg-2);
  255. bargv[bargc] = nil;
  256. cp = jehanne_strchr(reply, '!');
  257. if(cp)
  258. jehanne_strcpy(sys, cp+1);
  259. return mp;
  260. }
  261. static void
  262. usbinit(void)
  263. {
  264. Waitmsg *w;
  265. static char *argv[] = {"usbrc", nil};
  266. int pid;
  267. if (jehanne_access(usbrcPath, AEXIST) < 0) {
  268. jehanne_print("usbinit: no %s\n", usbrcPath);
  269. return;
  270. }
  271. switch(pid = jehanne_fork()){
  272. case -1:
  273. jehanne_print("usbinit: fork failed: %r\n");
  274. case 0:
  275. exec(usbrcPath, (const char**)argv);
  276. fatal("can't exec usbd");
  277. default:
  278. break;
  279. }
  280. jehanne_print("usbinit: waiting usbrc...");
  281. for(;;){
  282. w = jehanne_wait();
  283. if(w != nil && w->pid == pid){
  284. if(w->msg[0] != 0)
  285. fatal(w->msg);
  286. jehanne_free(w);
  287. break;
  288. } else if(w == nil) {
  289. fatal("configuring usbinit");
  290. } else if(w->msg[0] != 0){
  291. jehanne_print("usbinit: wait: %d %s\n", w->pid, w->msg);
  292. }
  293. jehanne_free(w);
  294. }
  295. jehanne_print("done\n");
  296. }
  297. static int
  298. startconsole(void)
  299. {
  300. char *dbgfile, *argv[16], **av;
  301. int i;
  302. if(jehanne_access(screenconsolePath, AEXEC) < 0){
  303. jehanne_print("cannot find screenconsole: %r\n");
  304. return -1;
  305. }
  306. /* start agent */
  307. i = 0;
  308. av = argv;
  309. av[i++] = "screenconsole";
  310. if(dbgfile = jehanne_getenv("debugconsole")){
  311. av[i++] = "-d";
  312. av[i++] = dbgfile;
  313. }
  314. av[i] = 0;
  315. switch(jehanne_fork()){
  316. case -1:
  317. fatal("starting screenconsole");
  318. case 0:
  319. exec(screenconsolePath, (const char**)av);
  320. fatal("execing screenconsole");
  321. default:
  322. break;
  323. }
  324. /* wait for agent to really be there */
  325. while(jehanne_access("#s/screenconsole", AEXIST) < 0){
  326. jehanne_sleep(250);
  327. }
  328. /* replace 0, 1 and 2 */
  329. if((i = open("#s/screenconsole", ORDWR)) < 0)
  330. fatal("open #s/screenconsole");
  331. if(mount(i, -1, "/dev", MBEFORE, "", '9') < 0)
  332. fatal("mount /dev");
  333. if((i = open("/dev/cons", OREAD))<0)
  334. fatal("open /dev/cons, OREAD");
  335. if(jehanne_dup(i, 0) != 0)
  336. fatal("jehanne_dup(i, 0)");
  337. close(i);
  338. if((i = open("/dev/cons", OWRITE))<0)
  339. fatal("open /dev/cons, OWRITE");
  340. if(jehanne_dup(i, 1) != 1)
  341. fatal("jehanne_dup(i, 1)");
  342. close(i);
  343. if(jehanne_dup(1, 2) != 2)
  344. fatal("jehanne_dup(1, 2)");
  345. return 0;
  346. }
  347. static int
  348. startcomconsole(void)
  349. {
  350. char *dbgfile, *argv[16], **av;
  351. int i;
  352. if(jehanne_access(comconsolePath, AEXEC) < 0){
  353. jehanne_print("cannot find comconsole: %r\n");
  354. return -1;
  355. }
  356. /* start agent */
  357. i = 0;
  358. av = argv;
  359. av[i++] = "comconsole";
  360. if(dbgfile = jehanne_getenv("debugconsole")){
  361. av[i++] = "-d";
  362. av[i++] = dbgfile;
  363. }
  364. av[i++] = "-s";
  365. av[i++] = "comconsole";
  366. av[i++] = "#t/eia0";
  367. av[i] = 0;
  368. switch(jehanne_fork()){
  369. case -1:
  370. fatal("starting comconsole");
  371. case 0:
  372. exec(comconsolePath, (const char**)av);
  373. fatal("execing comconsole");
  374. default:
  375. break;
  376. }
  377. /* wait for agent to really be there */
  378. while(jehanne_access("#s/comconsole", AEXIST) < 0){
  379. jehanne_sleep(250);
  380. }
  381. /* replace 0, 1 and 2 */
  382. if((i = open("#s/comconsole", ORDWR)) < 0)
  383. fatal("open #s/comconsole");
  384. if(mount(i, -1, "/dev", MBEFORE, "", '9') < 0)
  385. fatal("mount /dev");
  386. if((i = open("/dev/cons", OREAD))<0)
  387. fatal("open /dev/cons, OREAD");
  388. if(jehanne_dup(i, 0) != 0)
  389. fatal("jehanne_dup(i, 0)");
  390. close(i);
  391. if((i = open("/dev/cons", OWRITE))<0)
  392. fatal("open /dev/cons, OWRITE");
  393. if(jehanne_dup(i, 1) != 1)
  394. fatal("jehanne_dup(i, 1)");
  395. close(i);
  396. if(jehanne_dup(1, 2) != 2)
  397. fatal("jehanne_dup(1, 2)");
  398. return 0;
  399. }
  400. static void
  401. bindBoot(void)
  402. {
  403. BootBind *b = bootbinds;
  404. if(b == nil || b->name == nil)
  405. return;
  406. while(b->name){
  407. bind(b->name, b->old, b->flag);
  408. ++b;
  409. }
  410. }
  411. static void
  412. unbindBoot(void)
  413. {
  414. BootBind *b = bootbinds;
  415. if(b == nil || b->name == nil)
  416. return;
  417. while(b->name)
  418. ++b;
  419. while(--b >= bootbinds){
  420. unmount(b->name, b->old);
  421. }
  422. }
  423. static void
  424. kbmap(void)
  425. {
  426. char *f;
  427. int n, in, out;
  428. char buf[1024];
  429. f = jehanne_getenv("kbmap");
  430. if(f == nil)
  431. return;
  432. if(bind("#κ", "/dev", MAFTER) < 0){
  433. warning("can't bind #κ");
  434. return;
  435. }
  436. in = open(f, OREAD);
  437. if(in < 0){
  438. warning("can't open kbd map");
  439. return;
  440. }
  441. out = open("/dev/kbmap", OWRITE);
  442. if(out < 0) {
  443. warning("can't open /dev/kbmap");
  444. close(in);
  445. return;
  446. }
  447. while((n = read(in, buf, sizeof(buf))) > 0)
  448. if(write(out, buf, n) != n){
  449. warning("write to /dev/kbmap failed");
  450. break;
  451. }
  452. close(in);
  453. close(out);
  454. }