1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "io.h" 7 8 #include "dosfs.h" 9 10 typedef struct Type Type; 11 typedef struct Medium Medium; 12 typedef struct Mode Mode; 13 14 enum { 15 Dany = -1, 16 Nmedia = 16, 17 18 /* DS1 switch options */ 19 Sflashfs = 1<<0, /* take local fs from flash */ 20 Snotflash = 1<<1, /* don't boot from flash */ 21 }; 22 23 enum { /* type */ 24 Tflash, 25 Tuart, 26 Tether, 27 Thard, 28 29 Tany = -1, 30 }; 31 32 enum { /* flag and name */ 33 Fnone = 0x00, 34 35 Fdos = 0x01, 36 Ndos = 0x00, 37 Fboot = 0x02, 38 Nboot = 0x01, 39 Fbootp = 0x04, 40 Nbootp = 0x02, 41 Fflash = 0x08, 42 Fuart = 0x10, 43 NName = 0x03, 44 45 Fany = Fbootp|Fboot|Fdos|Fflash|Fuart, 46 47 Fini = 0x10, 48 Fprobe = 0x80, 49 }; 50 51 enum { /* mode */ 52 Mauto = 0x00, 53 Mlocal = 0x01, 54 Manual = 0x02, 55 NMode = 0x03, 56 }; 57 58 typedef struct Type { 59 int type; 60 char *cname; 61 int flag; 62 int (*init)(void); 63 long (*read)(int, void*, long); 64 long (*seek)(int, long); 65 Partition* (*setpart)(int, char*); 66 char* name[NName]; 67 68 int mask; 69 Medium* media; 70 } Type; 71 72 typedef struct Medium { 73 Type* type; 74 int flag; 75 Partition* partition; 76 Dos; 77 78 Medium* next; 79 } Medium; 80 81 typedef struct Mode { 82 char* name; 83 int mode; 84 } Mode; 85 86 static Type types[] = { 87 { Tflash, "flash", 88 Fflash, 89 flashinit, 0, 0, 0, 90 { 0, "F", 0, } 91 }, 92 /* 93 { Tuart, "uart", 94 Fuart|Fboot, 95 uartinit, uartread, uartseek, setuartpart, 96 { 0, "u", 0, } 97 }, 98 */ 99 { Tether, "ether", 100 Fbootp, 101 etherinit, 0, 0, 0, 102 { 0, 0, "e", }, 103 }, 104 { Thard, "ata", 105 Fini|Fboot|Fdos, 106 0, 0, 0, 0, /* not used now, will be later with PCMCIA */ 107 { "hd", "h", 0, }, 108 }, 109 {-1}, 110 }; 111 112 static Medium media[Nmedia]; 113 static Medium *curmedium = media; 114 115 static Mode modes[NMode+1] = { 116 [Mauto] { "auto", Mauto, }, 117 [Mlocal] { "local", Mlocal, }, 118 [Manual] { "manual", Manual, }, 119 }; 120 121 static char *inis[] = { 122 "inferno/inferno.ini", 123 "inferno.ini", 124 "plan9/plan9.ini", 125 "plan9.ini", 126 0, 127 }; 128 char **ini; 129 int predawn; 130 131 static int 132 parse(char *line, int *type, int *flag, int *dev, char *file) 133 { 134 Type *tp; 135 char buf[2*NAMELEN], *v[4], *p; 136 int i; 137 138 strcpy(buf, line); 139 switch(getcfields(buf, v, 4, "!")){ 140 141 case 3: 142 break; 143 144 case 2: 145 v[2] = ""; 146 break; 147 148 default: 149 return 0; 150 } 151 152 *flag = 0; 153 for(tp = types; tp->cname; tp++){ 154 for(i = 0; i < NName; i++){ 155 156 if(tp->name[i] == 0 || strcmp(v[0], tp->name[i])) 157 continue; 158 *type = tp->type; 159 *flag |= 1<<i; 160 161 if((*dev = strtoul(v[1], &p, 0)) == 0 && p == v[1]) 162 return 0; 163 164 strcpy(file, v[2]); 165 166 return 1; 167 } 168 } 169 170 return 0; 171 172 } 173 174 static int 175 boot(Medium *mp, int flag, char *file) 176 { 177 Dosfile df; 178 char ixdos[128], *p; 179 int r; 180 181 uartsetboot(0); 182 if(flag & Fbootp){ 183 sprint(BOOTLINE, "%s!%d", mp->type->name[Nbootp], mp->dev); 184 return bootp(mp->dev, file); 185 } 186 187 if(flag & Fflash){ 188 if(mp->flag & Fflash && flashbootable(0)) 189 flashboot(mp->dev); 190 } 191 192 if(flag & Fboot){ 193 194 if(mp->flag & Fini){ 195 (*mp->type->setpart)(mp->dev, "disk"); 196 plan9ini(mp, nil); 197 } 198 if(file == 0 || *file == 0) 199 file = mp->partition->name; 200 (*mp->type->setpart)(mp->dev, file); 201 sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Nboot], mp->dev, file); 202 r = plan9boot(mp->dev, mp->seek, mp->read); 203 uartsetboot(0); 204 return r; 205 } 206 207 if(flag & Fdos){ 208 if(mp->type->setpart) 209 (*mp->type->setpart)(mp->dev, "disk"); 210 if(mp->flag & Fini) 211 plan9ini(mp, nil); 212 if(file == 0 || *file == 0){ 213 strcpy(ixdos, *ini); 214 if(p = strrchr(ixdos, '/')) 215 p++; 216 else 217 p = ixdos; 218 strcpy(p, "impc"); 219 if(dosstat(mp, ixdos, &df) <= 0) 220 return -1; 221 } 222 else 223 strcpy(ixdos, file); 224 sprint(BOOTLINE, "%s!%d!%s", mp->type->name[Ndos], mp->dev, ixdos); 225 return dosboot(mp, ixdos); 226 } 227 228 return -1; 229 } 230 231 static Medium* 232 allocm(Type *tp) 233 { 234 Medium **l; 235 236 if(curmedium >= &media[Nmedia]) 237 return 0; 238 239 for(l = &tp->media; *l; l = &(*l)->next) 240 ; 241 *l = curmedium++; 242 return *l; 243 } 244 245 Medium* 246 probe(int type, int flag, int dev) 247 { 248 Type *tp; 249 int dombr, i, start; 250 Medium *mp; 251 Dosfile df; 252 Partition *pp; 253 254 for(tp = types; tp->cname; tp++){ 255 if(type != Tany && type != tp->type || tp->init == 0) 256 continue; 257 258 if(flag != Fnone){ 259 for(mp = tp->media; mp; mp = mp->next){ 260 if((flag & mp->flag) && (dev == Dany || dev == mp->dev)) 261 return mp; 262 } 263 } 264 if((tp->flag & Fprobe) == 0){ 265 tp->flag |= Fprobe; 266 tp->mask = (*tp->init)(); 267 } 268 269 for(i = 0; tp->mask; i++){ 270 if((tp->mask & (1<<i)) == 0) 271 continue; 272 tp->mask &= ~(1<<i); 273 274 if((mp = allocm(tp)) == 0) 275 continue; 276 277 mp->dev = i; 278 mp->flag = tp->flag; 279 mp->seek = tp->seek; 280 mp->read = tp->read; 281 mp->type = tp; 282 283 if(mp->flag & Fboot){ 284 if((mp->partition = (*tp->setpart)(i, "boot")) == 0) 285 mp->flag &= ~Fboot; 286 if((mp->flag & (Fflash|Fuart)) == 0) 287 (*tp->setpart)(i, "disk"); 288 } 289 290 if(mp->flag & Fdos){ 291 start = 0; 292 dombr = 1; 293 if(mp->type->setpart){ 294 if(pp = (*mp->type->setpart)(i, "dos")){ 295 if(start = pp->start) 296 dombr = 0; 297 } 298 (*tp->setpart)(i, "disk"); 299 } 300 if(dosinit(mp, start, dombr) < 0) 301 mp->flag &= ~(Fini|Fdos); 302 else 303 print("dos init failed\n"); 304 } 305 306 if(mp->flag & Fini){ 307 mp->flag &= ~Fini; 308 for(ini = inis; *ini; ini++){ 309 if(dosstat(mp, *ini, &df) <= 0) 310 continue; 311 mp->flag |= Fini; 312 break; 313 } 314 } 315 316 if((flag & mp->flag) && (dev == Dany || dev == i)) 317 return mp; 318 } 319 } 320 321 return 0; 322 } 323 324 void 325 main(void) 326 { 327 Medium *mp; 328 int dev, flag, i, mode, tried, type, options; 329 char def[2*NAMELEN], file[2*NAMELEN], line[80], *p; 330 Type *tp; 331 332 machinit(); 333 archinit(); 334 meminit(); 335 cpminit(); 336 trapinit(); 337 consinit(); /* screen and keyboard initially */ 338 screeninit(); 339 cpuidprint(); 340 alarminit(); 341 clockinit(); 342 predawn = 0; 343 spllo(); 344 options = archoptionsw(); 345 346 mp = 0; 347 for(tp = types; tp->cname; tp++){ 348 if(tp->type == Tether) 349 continue; 350 if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){ 351 plan9ini(mp, nil); 352 break; 353 } 354 } 355 356 if(mp == 0 || (mp->flag & Fini) == 0) 357 plan9ini(nil, flashconfig(0)); 358 359 //consinit(); /* establish new console location */ 360 361 if((options & Snotflash) == 0 && flashbootable(0)){ 362 print("Flash boot\n"); 363 flashboot(0); 364 } 365 366 tried = 0; 367 mode = Mauto; 368 p = getconf("bootfile"); 369 flag = 0; 370 371 if(p != 0) { 372 mode = Manual; 373 for(i = 0; i < NMode; i++){ 374 if(strcmp(p, modes[i].name) == 0){ 375 mode = modes[i].mode; 376 goto done; 377 } 378 } 379 if(parse(p, &type, &flag, &dev, file) == 0) { 380 print("Bad bootfile syntax: %s\n", p); 381 goto done; 382 } 383 mp = probe(type, flag, dev); 384 if(mp == 0) { 385 print("Cannot access device: %s\n", p); 386 goto done; 387 } 388 tried = boot(mp, flag, file); 389 } 390 done: 391 if(tried == 0 && mode != Manual){ 392 flag = Fany; 393 if(mode == Mlocal) 394 flag &= ~Fbootp; 395 if(options & Snotflash) 396 flag &= ~Fflash; 397 if((mp = probe(Tany, flag, Dany)) != 0) 398 boot(mp, flag & mp->flag, 0); 399 } 400 401 def[0] = 0; 402 probe(Tany, Fnone, Dany); 403 404 flag = 0; 405 for(tp = types; tp->cname; tp++){ 406 for(mp = tp->media; mp; mp = mp->next){ 407 if(flag == 0){ 408 flag = 1; 409 print("Boot devices:"); 410 } 411 412 if(mp->flag & Fbootp) 413 print(" %s!%d", mp->type->name[Nbootp], mp->dev); 414 if(mp->flag & Fdos) 415 print(" %s!%d", mp->type->name[Ndos], mp->dev); 416 if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot) 417 print(" %s!%d", mp->type->name[Nboot], mp->dev); 418 } 419 } 420 if(flag) 421 print("\n"); 422 423 for(;;){ 424 if(getstr("boot from", line, sizeof(line), def) >= 0){ 425 if(parse(line, &type, &flag, &dev, file)){ 426 if(mp = probe(type, flag, dev)) 427 boot(mp, flag, file); 428 } 429 } 430 def[0] = 0; 431 } 432 } 433 434 void 435 machinit(void) 436 { 437 memset(m, 0, sizeof(*m)); 438 m->delayloop = 20000; 439 m->cpupvr = getpvr(); 440 m->iomem = KADDR(INTMEM); 441 } 442 443 int 444 getcfields(char* lp, char** fields, int n, char* sep) 445 { 446 int i; 447 448 for(i = 0; lp && *lp && i < n; i++){ 449 while(*lp && strchr(sep, *lp) != 0) 450 *lp++ = 0; 451 if(*lp == 0) 452 break; 453 fields[i] = lp; 454 while(*lp && strchr(sep, *lp) == 0){ 455 if(*lp == '\\' && *(lp+1) == '\n') 456 *lp++ = ' '; 457 lp++; 458 } 459 } 460 461 return i; 462 } 463 464 static Map memv[512]; 465 static RMap rammap = {"physical memory"}; 466 467 void 468 meminit(void) 469 { 470 ulong e; 471 472 mapinit(&rammap, memv, sizeof(memv)); 473 e = PADDR(&end); 474 mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */ 475 } 476 477 void* 478 ialloc(ulong n, int align) 479 { 480 ulong a; 481 int s; 482 483 if(align <= 0) 484 align = 4; 485 s = splhi(); 486 a = mapalloc(&rammap, 0, n, align); 487 splx(s); 488 if(a == 0) 489 panic("ialloc"); 490 return memset(KADDR(a), 0, n); 491 } 492 493 void* 494 malloc(ulong n) 495 { 496 ulong *p; 497 498 n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int); 499 p = ialloc(n, sizeof(int)); 500 *p++ = 0xcafebeef; 501 *p++ = n; 502 return p; 503 } 504 505 void 506 free(void *ap) 507 { 508 int s; 509 ulong *p; 510 511 p = ap; 512 if(p){ 513 if(*(p -= 2) != 0xcafebeef) 514 panic("free"); 515 s = splhi(); 516 mapfree(&rammap, (ulong)p, p[1]); 517 splx(s); 518 } 519 } 520 521 void 522 sched(void) 523 { 524 } 525