1implement Init; 2 3include "sys.m"; 4 sys: Sys; 5 6include "draw.m"; 7 draw: Draw; 8 9include "keyring.m"; 10 kr: Keyring; 11 12include "security.m"; 13 auth: Auth; 14 15include "styx.m"; 16 17 dosfs : Dosfs; 18 19PROMPT: con 1; # boot from prompt? (0 means boot from fs) 20SHELL: con 0; # Start a Shell, not Logon 21INIT: con "/init"; # file to read init commands from 22 23startip := 0; 24 25Bootpreadlen: con 128; 26 27Init: module 28{ 29 init: fn(); 30}; 31 32Logon: module 33{ 34 init: fn(ctxt: ref Draw->Context, argv: list of string); 35}; 36 37Sh: module 38{ 39 init: fn(ctxt: ref Draw->Context, argv: list of string); 40}; 41 42lfs(dev: string): int 43{ 44 (ok, dir) := sys->stat(dev); 45 if (ok < 0) { 46 sys->print("init: stat %s: %r\n", dev); 47 return -1; 48 } 49 pipefd := array[2] of ref Sys->FD; 50 dosfs = load Dosfs "#/./dosfs"; 51 if(dosfs == nil) { 52 sys->fprint(sys->fildes(2),"load #/.dosfs: %r\n"); 53 return -1; 54 } 55 56 dosfs->init(dev, "", 0); 57 if(sys->pipe(pipefd) < 0){ 58 sys->fprint(sys->fildes(2),"pipe %r\n"); 59 exit; 60 } 61 spawn dosfs->dossrv(pipefd[1]); 62 63 n := sys->mount(pipefd[0], "/", sys->MREPL|sys->MCREATE, ""); 64 if(n<0) { 65 sys->print("couldn't mount. %r\n"); 66 return -1; 67 } 68 69 dosfs->setup(); 70 71 sys->print("mounted %s at /\n", dev); 72 73 return 0; 74} 75 76ipinit() 77{ 78 fd := sys->open("/nvfs/IP", sys->OREAD); 79 if(fd == nil) 80 return; 81 82 buf := array[128] of byte; 83 nr := sys->read(fd, buf, len buf); 84 if(nr <= 0) 85 return; 86 87 cfd := sys->open("/net/ipifc/clone", sys->ORDWR); 88 if(cfd == nil) { 89 sys->print("init: open /net/ipifc/clone: %r"); 90 exit; 91 } 92 93 sys->fprint(cfd, "bind ether ether0"); 94 sys->fprint(cfd, "%s", string buf[0:nr]); 95} 96 97netfs(): int 98{ 99 cfd := sys->open("/net/ipifc/clone", sys->ORDWR); 100 if(cfd == nil) { 101 sys->print("init: open /net/ipifc/clone: %r"); 102 exit; 103 } 104 sys->fprint(cfd, "bind ether ether0"); 105 106 server:= bootp(cfd); 107 sys->print("dial..."); 108 (ok, c) := sys->dial("tcp!" + server + "!6666", nil); 109 if(ok < 0) 110 return -1; 111 112 if(kr != nil && auth != nil){ 113 err: string; 114 sys->print("Authenticate ..."); 115 ai := kr->readauthinfo("/nvfs/default"); 116 if(ai == nil){ 117 sys->print("readauthinfo /nvfs/default failed: %r\n"); 118 sys->print("trying mount as `nobody'\n"); 119 } 120 (c.dfd, err) = auth->client("none", ai, c.dfd); 121 if(c.dfd == nil){ 122 sys->print("authentication failed: %s\n", err); 123 return -1; 124 } 125 } 126 127 sys->print("mount ..."); 128 129 c.cfd = nil; 130 n := sys->mount(c.dfd, "/", sys->MREPL, ""); 131 if(n > 0) 132 return 0; 133 134 return -1; 135} 136 137init() 138{ 139 spec: string; 140 141 sys = load Sys Sys->PATH; 142 kr = load Keyring Keyring->PATH; 143 auth = load Auth Auth->PATH; 144 if(auth != nil) 145 auth->init(); 146 147 sys->print("**\n** Inferno\n** Vita Nuova\n**\n\n\n"); 148 149 # 150 # Setup what we need to call a server and 151 # Authenticate 152 # 153 sys->bind("#l", "/net", sys->MREPL); 154 sys->bind("#I", "/net", sys->MAFTER); 155 sys->bind("#c", "/dev", sys->MAFTER); 156 157 sys->print("Non-volatile ram read ...\n"); 158 159 nvramfd := sys->open("#H/hd0nvram", sys->ORDWR); 160 if(nvramfd != nil) { 161 spec = "#Fhd0nvram"; 162 if(sys->bind(spec, "/nvfs", sys->MAFTER) < 0) 163 sys->print("init: bind %s: %r\n", spec); 164 sys->print("mounted tinyfs"); 165 nvramfd = nil; 166 } 167 168 sys->print("\n\n"); 169 170 if(!PROMPT) { 171 if(lfs("#H/hd0fs") == 0) 172 startip = 1; 173 else 174 bootfrom(); 175 } else 176 bootfrom(); 177 178 sys->bind("#l", "/net", sys->MBEFORE); 179 sys->bind("#I", "/net", sys->MBEFORE); 180 sys->bind("#c", "/dev", sys->MBEFORE); 181 182 if(startip) 183 ipinit(); 184 185 setsysname(); 186 187 sys->print("clock...\n"); 188 setclock(); 189 190 if(SHELL) { 191 sys->print("shell...\n"); 192 193 logon := load Logon "/dis/sh.dis"; 194 if(logon == nil) { 195 sys->print("init: load /dis/wm/logon.dis: %r"); 196 exit; 197 } 198 dc: ref Draw->Context; 199 spawn logon->init(dc, nil); 200 exit; 201 } 202 203 runprogs(); 204} 205 206bootfrom() 207{ 208 buf := array[128] of byte; 209 stdin := sys->fildes(0); 210 211 fsdev := "#H/hd0disk"; 212 213 loop: for(;;) { 214 sys->print("boot from [fs, net]: "); 215 216 n := sys->read(stdin, buf, len buf); 217 if(n <= 0) 218 continue; 219 if(buf[n-1] == byte '\n') 220 n--; 221 222 (nil, choice) := sys->tokenize(string buf[:n], "\t "); 223 if(choice == nil) 224 continue; 225 226 opt := hd choice; 227 choice = tl choice; 228 229 case opt { 230 * => 231 sys->print("\ninvalid boot option: '%s'\n", opt); 232 break; 233 "fs" or "" => 234 if(choice != nil) 235 fsdev = hd choice; 236 if(lfs(fsdev) == 0) { 237 startip = 1; 238 break loop; 239 } 240 "net" => 241 if(netfs() == 0) 242 break loop; 243 } 244 } 245} 246 247runprogs() 248{ 249 fd:= sys->open(INIT, Sys->OREAD); 250 if(fd == nil) { 251 sys->print("open %s: %r\n", INIT); 252 return; 253 } 254 255 dc := ref Draw->Context; 256 dc.ctomux = chan of int; 257 258 for(l:=1;;l++) { 259 (e, line):= getline(fd); 260 if(e != nil) { 261 sys->print(INIT+":%d: %s\n", l, e); 262 return; 263 } 264 if(line == nil) 265 break; 266 if(line == "\n" || line[0] == '#') 267 continue; 268 if(line[len line-1] == '\n') 269 line = line[:len line-1]; 270 (n, f):= sys->tokenize(line, " \t"); 271 if(n < 0) { 272 sys->print(INIT+":%d: tokenize: %r\n", l); 273 return; 274 } 275 if(n < 2) { 276 sys->print(INIT+":%d: not enough fields\n", l); 277 continue; 278 } 279 e = run(dc, f); 280 if(e != nil) 281 sys->print(INIT+":%d: %s\n", l, e); 282 } 283} 284 285run(dc: ref Draw->Context, argv: list of string): string 286{ 287 c:= hd argv; 288 argv = tl argv; 289 prog:= hd argv; 290 ext:= ".dis"; 291 if(prog[len prog-4:] == ".dis") 292 ext = ""; 293 sh:= load Sh prog+ext; 294 if(sh == nil) 295 sh = load Sh "/dis/"+prog+ext; 296 if(sh == nil) 297 return sys->sprint("%s: load: %r", prog); 298 299 case c { 300 "run" => 301 e:= ref Sys->Exception; 302 if(sys->rescue("fail:*", e)) 303 return prog+": "+e.name; 304 sh->init(dc, argv); 305 return nil; 306 "spawn" => 307 spawn sh->init(dc, argv); 308 return nil; 309 } 310 return c+": unknown command"; 311} 312 313getline(fd: ref Sys->FD): (string, string) 314{ 315 s:= ""; 316 buf:= array[1] of byte; 317 for(;;) { 318 n:= sys->read(fd, buf, 1); 319 if(n < 0) 320 return (sys->sprint("getline: read: %r\n"), nil); 321 if(n == 0) 322 return (nil, s); 323 s += string buf; 324 if(buf[0] == byte '\n') 325 return (nil, s); 326 } 327} 328 329setclock() 330{ 331 (ok, dir) := sys->stat("/"); 332 if (ok < 0) { 333 sys->print("init: stat /: %r"); 334 return; 335 } 336 337 fd := sys->open("/dev/time", sys->OWRITE); 338 if (fd == nil) { 339 sys->print("init: open /dev/time: %r\n"); 340 return; 341 } 342 343 # Time is kept as microsecs, atime is in secs 344 b := array of byte sys->sprint("%d000000", dir.atime); 345 if (sys->write(fd, b, len b) != len b) 346 sys->print("init: write /dev/time: %r"); 347} 348 349# 350# Set system name from nvram 351# 352setsysname() 353{ 354 fd := sys->open("/nvfs/ID", sys->OREAD); 355 if(fd == nil) 356 return; 357 fds := sys->open("/dev/sysname", sys->OWRITE); 358 if(fds == nil) 359 return; 360 buf := array[128] of byte; 361 nr := sys->read(fd, buf, len buf); 362 if(nr <= 0) 363 return; 364 sys->write(fds, buf, nr); 365} 366 367bootp(cfd: ref sys->FD): string 368{ 369 sys->print("bootp ..."); 370 371 sys->fprint(cfd, "bootp"); 372 373 fd := sys->open("/net/bootp", sys->OREAD); 374 if(fd == nil) { 375 sys->print("init: open /net/bootp: %r"); 376 exit; 377 } 378 379 380 buf := array[Bootpreadlen] of byte; 381 nr := sys->read(fd, buf, len buf); 382 fd = nil; 383 if(nr <= 0) { 384 sys->print("init: read /net/bootp: %r"); 385 exit; 386 } 387 (ntok, ls) := sys->tokenize(string buf, " \t\n"); 388 while(ls != nil) { 389 if(hd ls == "fsip"){ 390 ls = tl ls; 391 break; 392 } 393 ls = tl ls; 394 } 395 if(ls == nil) { 396 sys->print("init: server address not in bootp read"); 397 exit; 398 } 399 400 srv := hd ls; 401 402 sys->print("(ip=%s)", srv); 403 404 return srv; 405} 406