1implement Init; 2# 3# init program for Motorola 800 series (serial console only) 4# 5include "sys.m"; 6 sys: Sys; 7 8include "draw.m"; 9 draw: Draw; 10 11include "keyring.m"; 12 kr: Keyring; 13 14include "security.m"; 15 auth: Auth; 16 17Init: module 18{ 19 init: fn(); 20}; 21 22Shell: module 23{ 24 init: fn(ctxt: ref Draw->Context, argv: list of string); 25}; 26 27Bootpreadlen: con 128; 28 29# option switches 30UseLocalFS: con 1<<0; 31EtherBoot: con 1<<1; 32Prompting: con 1<<3; 33 34lfs(): int 35{ 36 if(!ftlinit("#F/flash/flash", 1024*1024, 1024*1024)) 37 return -1; 38 if(mountkfs("#X/ftldata", "main", "flash") < 0) 39 return -1; 40 if(sys->bind("#Kmain", "/n/local", sys->MREPL) < 0){ 41 sys->print("can't bind #Kmain to /n/local: %r\n"); 42 return -1; 43 } 44 if(sys->bind("/n/local", "/", Sys->MCREATE|Sys->MREPL) < 0){ 45 sys->print("can't bind /n/local after /: %r\n"); 46 return -1; 47 } 48 return 0; 49} 50 51donebind := 0; 52 53# 54# set up network mount 55# 56netfs(mountpt: string): int 57{ 58 sys->print("bootp ..."); 59 60 fd: ref Sys->FD; 61 if(!donebind){ 62 fd = sys->open("/net/ipifc/clone", sys->OWRITE); 63 if(fd == nil) { 64 sys->print("init: open /net/ipifc/clone: %r\n"); 65 return -1; 66 } 67 if(sys->fprint(fd, "bind ether %s", "/net/ether0") < 0) { 68 sys->print("could not bind ether0 interface: %r\n"); 69 return -1; 70 } 71 donebind = 1; 72 }else{ 73 fd = sys->open("/net/ipifc/0/ctl", Sys->OWRITE); 74 if(fd == nil){ 75 sys->print("init: can't reopen /net/ipifc/0/ctl: %r\n"); 76 return -1; 77 } 78 } 79 if(sys->fprint(fd, "bootp") < 0){ 80 sys->print("init: bootp failed: %r\n"); 81 return -1; 82 } 83 84 server := bootp(); 85 if(server == nil) 86 return -1; 87 88 net := "tcp"; # how to specify il? 89 svcname := net + "!" + server + "!6666"; 90 91 sys->print("dial %s...", svcname); 92 93 (ok, c) := sys->dial(svcname, nil); 94 if(ok < 0){ 95 sys->print("can't dial %s: %r\n", svcname); 96 return -1; 97 } 98 99 sys->print("\nConnected ...\n"); 100 if(kr != nil){ 101 err: string; 102 sys->print("Authenticate ..."); 103 ai := kr->readauthinfo("/nvfs/default"); 104 if(ai == nil){ 105 sys->print("readauthinfo /nvfs/default failed: %r\n"); 106 sys->print("trying mount as `nobody'\n"); 107 } 108 (c.dfd, err) = auth->client("none", ai, c.dfd); 109 if(c.dfd == nil){ 110 sys->print("authentication failed: %s\n", err); 111 return -1; 112 } 113 } 114 115 sys->print("mount %s...", mountpt); 116 117 c.cfd = nil; 118 n := sys->mount(c.dfd, nil, mountpt, sys->MREPL, ""); 119 if(n > 0) 120 return 0; 121 if(n < 0) 122 sys->print("%r"); 123 return -1; 124} 125 126init() 127{ 128 sys = load Sys Sys->PATH; 129 kr = load Keyring Keyring->PATH; 130 auth = load Auth Auth->PATH; 131 if(auth != nil) 132 auth->init(); 133 134 sys->print("**\n** Inferno\n** Vita Nuova\n**\n"); 135 136 optsw := options(); 137 sys->print("Switch options: 0x%ux\n", optsw); 138 139 # 140 # Setup what we need to call a server and 141 # Authenticate 142 # 143 sys->bind("#l", "/net", sys->MREPL); 144 sys->bind("#I", "/net", sys->MAFTER); 145 sys->bind("#c", "/dev", sys->MAFTER); 146 147 fsready := 0; 148 mountpt := "/"; 149 usertc := 0; 150 151 if((optsw & Prompting) == 0){ 152 if(optsw & UseLocalFS){ 153 sys->print("Option: use local file system\n"); 154 if(lfs() == 0){ 155 fsready = 1; 156 mountpt = "/n/remote"; 157 } 158 } 159 160 if(optsw & EtherBoot){ 161 sys->print("Attempting remote mount\n"); 162 if(netfs(mountpt) == 0) 163 fsready = 1; 164 } 165 } 166 167 if(fsready == 0){ 168 169 sys->print("\n\n"); 170 171 stdin := sys->fildes(0); 172 buf := array[128] of byte; 173 sources := "fs" :: "net" :: nil; 174 175 loop: for(;;) { 176 sys->print("root from ("); 177 cm := ""; 178 for(l := sources; l != nil; l = tl l){ 179 sys->print("%s%s", cm, hd l); 180 cm = ","; 181 } 182 sys->print(")[%s] ", hd sources); 183 184 n := sys->read(stdin, buf, len buf); 185 if(n <= 0) 186 continue; 187 if(buf[n-1] == byte '\n') 188 n--; 189 190 (nil, choice) := sys->tokenize(string buf[0:n], "\t "); 191 192 if(choice == nil) 193 choice = sources; 194 opt := hd choice; 195 case opt { 196 * => 197 sys->print("\ninvalid boot option: '%s'\n", opt); 198 break; 199 "fs" or "" => 200 if(lfs() == 0){ 201 usertc = 1; 202 break loop; 203 } 204 "net" => 205 if(netfs("/") == 0) 206 break loop; 207 } 208 } 209 } 210 211 # 212 # default namespace 213 # 214 sys->unmount(nil, "/dev"); 215 sys->bind("#c", "/dev", sys->MBEFORE); # console 216 sys->bind("#l", "/net", sys->MBEFORE); # ethernet 217 sys->bind("#I", "/net", sys->MBEFORE); # TCP/IP 218 sys->bind("#p", "/prog", sys->MREPL); # prog device 219 sys->bind("#d", "/fd", Sys->MREPL); 220 221 setsysname(); 222 223 sys->print("clock...\n"); 224 setclock(usertc, mountpt); 225 226 sys->print("Console...\n"); 227 228 shell := load Shell "/dis/sh.dis"; 229 if(shell == nil) { 230 sys->print("init: load /dis/sh.dis: %r"); 231 exit; 232 } 233 dc: ref Draw->Context; 234 shell->init(dc, nil); 235} 236 237setclock(usertc: int, timedir: string) 238{ 239 now := 0; 240 if(usertc){ 241 fd := sys->open("#r/rtc", Sys->OREAD); 242 if(fd != nil){ 243 b := array[64] of byte; 244 n := sys->read(fd, b, len b-1); 245 if(n > 0){ 246 b[n] = byte 0; 247 now = int string b; 248 if(now <= 16r20000000) 249 now = 0; # rtc itself is not initialised 250 } 251 } 252 } 253 if(now == 0){ 254 (ok, dir) := sys->stat(timedir); 255 if (ok < 0) { 256 sys->print("init: stat %s: %r", timedir); 257 return; 258 } 259 now = dir.atime; 260 } 261 fd := sys->open("/dev/time", sys->OWRITE); 262 if (fd == nil) { 263 sys->print("init: can't open /dev/time: %r"); 264 return; 265 } 266 267 # Time is kept as microsecs, atime is in secs 268 b := array of byte sys->sprint("%ud000000", now); 269 if (sys->write(fd, b, len b) != len b) 270 sys->print("init: can't write /dev/time: %r"); 271} 272 273# 274# Set system name from nvram 275# 276setsysname() 277{ 278 fd := sys->open("/nvfs/ID", sys->OREAD); 279 if(fd == nil) 280 return; 281 fds := sys->open("/dev/sysname", sys->OWRITE); 282 if(fds == nil) 283 return; 284 buf := array[128] of byte; 285 nr := sys->read(fd, buf, len buf); 286 if(nr <= 0) 287 return; 288 sys->write(fds, buf, nr); 289} 290 291# 292# fetch options from switch DS2 293# 294options(): int 295{ 296 fd := sys->open("#r/switch", Sys->OREAD); 297 if(fd == nil){ 298 sys->print("can't open #r/switch: %r\n"); 299 return 0; 300 } 301 b := array[20] of byte; 302 n := sys->read(fd, b, len b); 303 s := string b[0:n]; 304 return int s; 305} 306 307bootp(): string 308{ 309 fd := sys->open("/net/bootp", sys->OREAD); 310 if(fd == nil) { 311 sys->print("init: can't open /net/bootp: %r"); 312 return nil; 313 } 314 315 buf := array[Bootpreadlen] of byte; 316 nr := sys->read(fd, buf, len buf); 317 fd = nil; 318 if(nr <= 0) { 319 sys->print("init: read /net/bootp: %r"); 320 return nil; 321 } 322 323 (ntok, ls) := sys->tokenize(string buf, " \t\n"); 324 while(ls != nil) { 325 if(hd ls == "fsip"){ 326 ls = tl ls; 327 break; 328 } 329 ls = tl ls; 330 } 331 if(ls == nil) { 332 sys->print("init: server address not in bootp read"); 333 return nil; 334 } 335 336 srv := hd ls; 337 338 sys->print("%s\n", srv); 339 340 return srv; 341} 342 343# 344# set up flash translation layer 345# 346ftldone := 0; 347 348ftlinit(flashmem: string, offset: int, length: int): int 349{ 350 if(ftldone) 351 return 1; 352 sys->print("Set flash translation of %s at offset %d (%d bytes)\n", flashmem, offset, length); 353 fd := sys->open("#X/ftlctl", Sys->OWRITE); 354 if(fd == nil){ 355 sys->print("can't open #X/ftlctl: %r\n"); 356 return 0; 357 } 358 if(sys->fprint(fd, "init %s %ud %ud", flashmem, offset, length) <= 0){ 359 sys->print("can't init flash translation: %r"); 360 return 0; 361 } 362 ftldone = 1; 363 return 1; 364} 365 366# 367# Mount kfs filesystem 368# 369mountkfs(devname: string, fsname: string, options: string): int 370{ 371 fd := sys->open("#Kcons/kfsctl", sys->OWRITE); 372 if(fd == nil) { 373 sys->print("could not open #Kcons/kfsctl: %r\n"); 374 return -1; 375 } 376 if(sys->fprint(fd, "filsys %s %s %s", fsname, devname, options) <= 0){ 377 sys->print("could not write #Kcons/kfsctl: %r\n"); 378 return -1; 379 } 380 if(options == "ro") 381 sys->fprint(fd, "cons flashwrite"); 382 return 0; 383} 384