cerfinit.b 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. #
  2. # Intrinsyc Cerf cube
  3. #
  4. implement Init;
  5. include "sys.m";
  6. sys: Sys;
  7. include "draw.m";
  8. include "keyring.m";
  9. kr: Keyring;
  10. include "security.m";
  11. auth: Auth;
  12. include "sh.m";
  13. Init: module
  14. {
  15. init: fn();
  16. };
  17. Bootpreadlen: con 128;
  18. # standard flash partitions
  19. flashparts := array[] of {
  20. # bootstrap at 0x0 to 0x20000
  21. "add script 0x20000 0x40000",
  22. "add kernel 0x100000 0x200000",
  23. "add fs 0x200000 end",
  24. };
  25. ethername := "ether0";
  26. #
  27. # initialise flash translation
  28. # mount flash file system
  29. # add devices
  30. # start a shell or window manager
  31. #
  32. init()
  33. {
  34. sys = load Sys Sys->PATH;
  35. kr = load Keyring Keyring->PATH;
  36. auth = load Auth Auth->PATH;
  37. if(auth != nil)
  38. auth->init();
  39. sys->bind("/", "/", Sys->MREPL);
  40. localok := 0;
  41. if(lfs() >= 0){
  42. # let's just take a closer look
  43. sys->bind("/n/local/nvfs", "/nvfs", Sys->MREPL|Sys->MCREATE);
  44. (rc, nil) := sys->stat("/n/local/dis/sh.dis");
  45. if(rc >= 0)
  46. localok = 1;
  47. else
  48. err("local file system unusable");
  49. }
  50. netok := sys->bind("#l", "/net", Sys->MREPL) >= 0;
  51. if(!netok){
  52. netok = sys->bind("#l1", "/net", Sys->MREPL) >= 0;
  53. if(netok)
  54. ethername = "ether1";
  55. }
  56. if(netok)
  57. configether();
  58. dobind("#I", "/net", sys->MAFTER); # IP
  59. dobind("#p", "/prog", sys->MREPL); # prog
  60. sys->bind("#d", "/fd", Sys->MREPL);
  61. dobind("#c", "/dev", sys->MREPL); # console
  62. dobind("#t", "/dev", sys->MAFTER); # serial line
  63. drawok := sys->bind("#i", "/dev", sys->MAFTER) >= 0; # draw
  64. sys->bind("#m", "/dev", sys->MAFTER); # pointer
  65. sys->bind("#e", "/env", sys->MREPL|sys->MCREATE); # environment
  66. sys->bind("#A", "/dev", Sys->MAFTER); # optional audio
  67. timefile: string;
  68. rootsource: string;
  69. scale := 1;
  70. cfd := sys->open("/dev/consctl", Sys->OWRITE);
  71. if(cfd != nil)
  72. sys->fprint(cfd, "rawon");
  73. for(;;){
  74. (rootsource, timefile, scale) = askrootsource(localok, netok);
  75. if(rootsource == nil)
  76. break; # internal
  77. (rc, nil) := sys->stat(rootsource+"/dis/sh.dis");
  78. if(rc < 0)
  79. err("%s has no shell");
  80. else if(sys->bind(rootsource, "/", Sys->MAFTER) < 0)
  81. sys->print("can't bind %s on /: %r\n", rootsource);
  82. else{
  83. sys->bind(rootsource+"/dis", "/dis", Sys->MBEFORE|Sys->MCREATE);
  84. break;
  85. }
  86. }
  87. cfd = nil;
  88. setsysname("cerf"); # set system name
  89. now := getclock(timefile, rootsource);
  90. if(scale == 1)
  91. now *= big 1000000;
  92. setclock("/dev/time", now);
  93. if(timefile != "#r/rtc")
  94. setclock("#r/rtc", now/big 1000000);
  95. sys->chdir("/");
  96. if(netok){
  97. start("ndb/dns", nil);
  98. start("ndb/cs", nil);
  99. }
  100. startup := "/nvfs/startup";
  101. if(sys->open(startup, Sys->OREAD) != nil){
  102. shell := load Command Sh->PATH;
  103. if(shell != nil){
  104. sys->print("Running %s\n", startup);
  105. shell->init(nil, "sh" :: startup :: nil);
  106. }
  107. }
  108. user := username("inferno");
  109. (ok, nil) := sys->stat("/dis/wm/wm.dis");
  110. if(drawok && ok >= 0)
  111. (ok, nil) = sys->stat("/dis/wm/logon.dis");
  112. if(drawok && ok >= 0 && userok(user)){
  113. wm := load Command "/dis/wm/wm.dis";
  114. if(wm != nil){
  115. fd := sys->open("/nvfs/user", Sys->OWRITE);
  116. if(fd != nil){
  117. sys->fprint(fd, "%s", user);
  118. fd = nil;
  119. }
  120. spawn wm->init(nil, list of {"wm/wm", "wm/logon", "-l", "-u", user});
  121. exit;
  122. }
  123. sys->print("init: can't load wm/logon: %r");
  124. }
  125. sh := load Command Sh->PATH;
  126. if(sh == nil){
  127. err(sys->sprint("can't load %s: %r", Sh->PATH));
  128. hang();
  129. }
  130. spawn sh->init(nil, "sh" :: nil);
  131. }
  132. start(cmd: string, args: list of string)
  133. {
  134. disfile := cmd;
  135. if(disfile[0] != '/')
  136. disfile = "/dis/"+disfile+".dis";
  137. (ok, nil) := sys->stat(disfile);
  138. if(ok >= 0){
  139. dis := load Command disfile;
  140. if(dis == nil)
  141. sys->print("init: can't load %s: %r\n", disfile);
  142. else
  143. spawn dis->init(nil, cmd :: args);
  144. }
  145. }
  146. dobind(f, t: string, flags: int)
  147. {
  148. if(sys->bind(f, t, flags) < 0)
  149. err(sys->sprint("can't bind %s on %s: %r", f, t));
  150. }
  151. #
  152. # Set system name from nvram if possible
  153. #
  154. setsysname(def: string)
  155. {
  156. v := array of byte def;
  157. fd := sys->open("/nvfs/ID", sys->OREAD);
  158. if(fd == nil)
  159. fd = sys->open("/env/sysname", sys->OREAD);
  160. if(fd != nil){
  161. buf := array[Sys->NAMEMAX] of byte;
  162. nr := sys->read(fd, buf, len buf);
  163. while(nr > 0 && buf[nr-1] == byte '\n')
  164. nr--;
  165. if(nr > 0)
  166. v = buf[0:nr];
  167. }
  168. fd = sys->open("/dev/sysname", sys->OWRITE);
  169. if(fd != nil)
  170. sys->write(fd, v, len v);
  171. }
  172. getclock(timefile: string, timedir: string): big
  173. {
  174. now := big 0;
  175. if(timefile != nil){
  176. fd := sys->open(timefile, Sys->OREAD);
  177. if(fd != nil){
  178. b := array[64] of byte;
  179. n := sys->read(fd, b, len b-1);
  180. if(n > 0){
  181. now = big string b[0:n];
  182. if(now <= big 16r20000000)
  183. now = big 0; # remote itself is not initialised
  184. }
  185. }
  186. }
  187. if(now == big 0){
  188. if(timedir != nil){
  189. (ok, dir) := sys->stat(timedir);
  190. if(ok < 0) {
  191. sys->print("init: stat %s: %r", timedir);
  192. return big 0;
  193. }
  194. now = big dir.atime;
  195. }else{
  196. now = big 993826747000000;
  197. sys->print("time warped\n");
  198. }
  199. }
  200. return now;
  201. }
  202. setclock(timefile: string, now: big)
  203. {
  204. fd := sys->open(timefile, sys->OWRITE);
  205. if (fd == nil) {
  206. sys->print("init: can't open %s: %r", timefile);
  207. return;
  208. }
  209. b := sys->aprint("%ubd", now);
  210. if (sys->write(fd, b, len b) != len b)
  211. sys->print("init: can't write to %s: %r", timefile);
  212. }
  213. srv()
  214. {
  215. sys->print("remote debug srv...");
  216. fd := sys->open("/dev/eia0ctl", Sys->OWRITE);
  217. if(fd != nil)
  218. sys->fprint(fd, "b115200");
  219. fd = sys->open("/dev/eia0", Sys->ORDWR);
  220. if (fd == nil){
  221. err(sys->sprint("can't open /dev/eia0: %r"));
  222. return;
  223. }
  224. if (sys->export(fd, "/", Sys->EXPASYNC) < 0){
  225. err(sys->sprint("can't export on serial port: %r"));
  226. return;
  227. }
  228. }
  229. err(s: string)
  230. {
  231. sys->fprint(sys->fildes(2), "init: %s\n", s);
  232. }
  233. hang()
  234. {
  235. <-chan of int;
  236. }
  237. tried := 0;
  238. askrootsource(localok: int, netok: int): (string, string, int)
  239. {
  240. stdin := sys->fildes(0);
  241. sources := "kernel" :: nil;
  242. if(netok)
  243. sources = "remote" :: sources;
  244. if(localok){
  245. sources = "local" :: sources;
  246. if(netok)
  247. sources = "local+remote" :: sources;
  248. }
  249. for(;;) {
  250. s := "";
  251. if (tried == 0 && (s = rf("/nvfs/rootsource", nil)) != nil) {
  252. tried = 1;
  253. if (s[len s - 1] == '\n')
  254. s = s[:len s - 1];
  255. sys->print("/nvfs/rootsource: root from %s\n", s);
  256. } else {
  257. sys->print("root from (");
  258. cm := "";
  259. for(l := sources; l != nil; l = tl l){
  260. sys->print("%s%s", cm, hd l);
  261. cm = ",";
  262. }
  263. sys->print(")[%s] ", hd sources);
  264. s = getline(stdin, hd sources); # default
  265. }
  266. (nil, choice) := sys->tokenize(s, "\t ");
  267. if(choice == nil)
  268. choice = sources;
  269. opt := hd choice;
  270. case opt {
  271. * =>
  272. sys->print("\ninvalid boot option: '%s'\n", opt);
  273. "kernel" =>
  274. return (nil, "#r/rtc", 1);
  275. "local" =>
  276. return ("/n/local", "#r/rtc", 1);
  277. "local+remote" =>
  278. if(netfs("/n/remote") >= 0)
  279. return ("/n/local", "/n/remote/dev/time", 1000000);
  280. "remote" =>
  281. if(netfs("/n/remote") >= 0)
  282. return ("/n/remote", "/n/remote/dev/time", 1000000);
  283. }
  284. }
  285. }
  286. getline(fd: ref Sys->FD, default: string): string
  287. {
  288. result := "";
  289. buf := array[10] of byte;
  290. i := 0;
  291. for(;;) {
  292. n := sys->read(fd, buf[i:], len buf - i);
  293. if(n < 1)
  294. break;
  295. i += n;
  296. while(i >0 && (nutf := sys->utfbytes(buf, i)) > 0){
  297. s := string buf[0:nutf];
  298. for (j := 0; j < len s; j++)
  299. case s[j] {
  300. '\b' =>
  301. if(result != nil)
  302. result = result[0:len result-1];
  303. 'u'&16r1F =>
  304. sys->print("^U\n");
  305. result = "";
  306. '\r' =>
  307. ;
  308. * =>
  309. sys->print("%c", s[j]);
  310. if(s[j] == '\n' || s[j] >= 16r80){
  311. if(s[j] != '\n')
  312. result[len result] = s[j];
  313. if(result == nil)
  314. return default;
  315. return result;
  316. }
  317. result[len result] = s[j];
  318. }
  319. buf[0:] = buf[nutf:i];
  320. i -= nutf;
  321. }
  322. }
  323. return default;
  324. }
  325. #
  326. # serve local DOS file system using flash translation layer
  327. #
  328. lfs(): int
  329. {
  330. if(!flashpart("#F/flash/flashctl", flashparts))
  331. return -1;
  332. if(!ftlinit("#F/flash/fs"))
  333. return -1;
  334. c := chan of string;
  335. spawn startfs(c, "/dis/dossrv.dis", "dossrv" :: "-f" :: "#X/ftldata" :: "-m" :: "/n/local" :: nil);
  336. if(<-c != nil)
  337. return -1;
  338. return 0;
  339. }
  340. startfs(c: chan of string, file: string, args: list of string)
  341. {
  342. fs := load Command file;
  343. if(fs == nil){
  344. sys->print("can't load %s: %r\n", file);
  345. c <-= "load failed";
  346. }
  347. {
  348. fs->init(nil, args);
  349. }exception e {
  350. "*" =>
  351. c <-= "failed";
  352. exit;
  353. * =>
  354. c <-= "unknown exception";
  355. exit;
  356. }
  357. c <-= nil;
  358. }
  359. #
  360. # partition flash
  361. #
  362. flashdone := 0;
  363. flashpart(ctl: string, parts: array of string): int
  364. {
  365. if(flashdone)
  366. return 1;
  367. cfd := sys->open(ctl, Sys->ORDWR);
  368. if(cfd == nil){
  369. sys->print("can't open %s: %r\n", ctl);
  370. return 0;
  371. }
  372. for(i := 0; i < len parts; i++)
  373. if(sys->fprint(cfd, "%s", parts[i]) < 0){
  374. sys->print("can't %q to %s: %r\n", parts[i], ctl);
  375. return 0;
  376. }
  377. flashdone = 1;
  378. return 1;
  379. }
  380. #
  381. # set up flash translation layer
  382. #
  383. ftldone := 0;
  384. ftlinit(flashmem: string): int
  385. {
  386. if(ftldone)
  387. return 1;
  388. sys->print("Set flash translation of %s...\n", flashmem);
  389. fd := sys->open("#X/ftlctl", Sys->OWRITE);
  390. if(fd == nil){
  391. sys->print("can't open #X/ftlctl: %r\n");
  392. return 0;
  393. }
  394. if(sys->fprint(fd, "init %s", flashmem) <= 0){
  395. sys->print("can't init flash translation: %r\n");
  396. return 0;
  397. }
  398. ftldone = 1;
  399. return 1;
  400. }
  401. configether()
  402. {
  403. if(ethername == nil)
  404. return;
  405. fd := sys->open("/nvfs/etherparams", Sys->OREAD);
  406. if(fd == nil)
  407. return;
  408. ctl := sys->open("/net/"+ethername+"/clone", Sys->OWRITE);
  409. if(ctl == nil){
  410. sys->print("init: can't open %s's clone: %r\n", ethername);
  411. return;
  412. }
  413. b := array[1024] of byte;
  414. n := sys->read(fd, b, len b);
  415. if(n <= 0)
  416. return;
  417. for(i := 0; i < n;){
  418. for(e := i; e < n && b[e] != byte '\n'; e++)
  419. ;
  420. s := string b[i:e];
  421. if(sys->fprint(ctl, "%s", s) < 0)
  422. sys->print("init: ctl write to %s: %s: %r\n", ethername, s);
  423. i = e+1;
  424. }
  425. }
  426. donebind := 0;
  427. #
  428. # set up network mount
  429. #
  430. netfs(mountpt: string): int
  431. {
  432. sys->print("bootp ...");
  433. fd: ref Sys->FD;
  434. if(!donebind){
  435. fd = sys->open("/net/ipifc/clone", sys->OWRITE);
  436. if(fd == nil) {
  437. sys->print("init: open /net/ipifc/clone: %r\n");
  438. return -1;
  439. }
  440. if(sys->fprint(fd, "bind ether %s", ethername) < 0) {
  441. sys->print("could not bind %s interface: %r\n", ethername);
  442. return -1;
  443. }
  444. donebind = 1;
  445. }else{
  446. fd = sys->open("/net/ipifc/0/ctl", Sys->OWRITE);
  447. if(fd == nil){
  448. sys->print("init: can't reopen /net/ipifc/0/ctl: %r\n");
  449. return -1;
  450. }
  451. }
  452. if ((ip := rf("/nvfs/ip", nil)) != nil) {
  453. sys->print("**using %s\n", ip);
  454. sys->fprint(fd, "bind ether /net/ether0");
  455. sys->fprint(fd, "add %s ", ip);
  456. } else {
  457. {
  458. if(sys->fprint(fd, "bootp") < 0)
  459. sys->print("could not bootp: %r\n");
  460. } exception e {
  461. "*" =>
  462. sys->print("could not bootp: %s\n", e);
  463. }
  464. }
  465. server := rf("/nvfs/fsip", nil);
  466. if (server != nil) {
  467. if (server[len server - 1] == '\n')
  468. server = server[:len server - 1];
  469. sys->print("/nvfs/fsip: server=%s\n", server);
  470. } else
  471. server = bootp();
  472. if(server == nil || server == "0.0.0.0")
  473. return -1;
  474. net := "tcp"; # how to specify il?
  475. svcname := net + "!" + server + "!6666";
  476. sys->print("dial %s...", svcname);
  477. (ok, c) := sys->dial(svcname, nil);
  478. if(ok < 0){
  479. sys->print("can't dial %s: %r\n", svcname);
  480. return -1;
  481. }
  482. sys->print("\nConnected ...\n");
  483. if(kr != nil){
  484. err: string;
  485. sys->print("Authenticate ...");
  486. ai := kr->readauthinfo("/nvfs/default");
  487. if(ai == nil){
  488. sys->print("readauthinfo /nvfs/default failed: %r\n");
  489. sys->print("trying mount as `nobody'\n");
  490. }
  491. (c.dfd, err) = auth->client("none", ai, c.dfd);
  492. if(c.dfd == nil){
  493. sys->print("authentication failed: %s\n", err);
  494. return -1;
  495. }
  496. }
  497. sys->print("mount %s...", mountpt);
  498. c.cfd = nil;
  499. n := sys->mount(c.dfd, nil, mountpt, sys->MREPL, "");
  500. if(n > 0)
  501. return 0;
  502. if(n < 0)
  503. sys->print("%r");
  504. return -1;
  505. }
  506. bootp(): string
  507. {
  508. fd := sys->open("/net/bootp", sys->OREAD);
  509. if(fd == nil) {
  510. sys->print("init: can't open /net/bootp: %r");
  511. return nil;
  512. }
  513. buf := array[Bootpreadlen] of byte;
  514. nr := sys->read(fd, buf, len buf);
  515. fd = nil;
  516. if(nr <= 0) {
  517. sys->print("init: read /net/bootp: %r");
  518. return nil;
  519. }
  520. (ntok, ls) := sys->tokenize(string buf, " \t\n");
  521. while(ls != nil) {
  522. if(hd ls == "fsip"){
  523. ls = tl ls;
  524. break;
  525. }
  526. ls = tl ls;
  527. }
  528. if(ls == nil) {
  529. sys->print("init: server address not in bootp read");
  530. return nil;
  531. }
  532. srv := hd ls;
  533. sys->print("%s\n", srv);
  534. return srv;
  535. }
  536. username(def: string): string
  537. {
  538. return rf("/nvfs/user", def);
  539. }
  540. userok(user: string): int
  541. {
  542. (ok, d) := sys->stat("/usr/"+user);
  543. return ok >= 0 && (d.mode & Sys->DMDIR) != 0;
  544. }
  545. rf(file: string, default: string): string
  546. {
  547. fd := sys->open(file, Sys->OREAD);
  548. if(fd != nil){
  549. buf := array[128] of byte;
  550. nr := sys->read(fd, buf, len buf);
  551. if(nr > 0)
  552. return string buf[0:nr];
  553. }
  554. return default;
  555. }