boot.c 7.5 KB

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