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