boot.c 6.5 KB

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