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 print("predawn\n"); 343 predawn = 0; 344 spllo(); 345 print("dawn\n"); 346 options = archoptionsw(); 347 print("options=#%ux\n", options); 348 349 mp = 0; 350 for(tp = types; tp->cname; tp++){ 351 if(tp->type == Tether) 352 continue; 353 if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){ 354 plan9ini(mp, nil); 355 break; 356 } 357 } 358 359 if(mp == 0 || (mp->flag & Fini) == 0) 360 plan9ini(nil, flashconfig(0)); 361 362 //consinit(); /* establish new console location */ 363 364 if((options & Snotflash) == 0 && flashbootable(0)){ 365 print("Flash boot\n"); 366 flashboot(0); 367 } 368 369 tried = 0; 370 mode = Mauto; 371 p = getconf("bootfile"); 372 flag = 0; 373 374 if(p != 0) { 375 mode = Manual; 376 for(i = 0; i < NMode; i++){ 377 if(strcmp(p, modes[i].name) == 0){ 378 mode = modes[i].mode; 379 goto done; 380 } 381 } 382 if(parse(p, &type, &flag, &dev, file) == 0) { 383 print("Bad bootfile syntax: %s\n", p); 384 goto done; 385 } 386 mp = probe(type, flag, dev); 387 if(mp == 0) { 388 print("Cannot access device: %s\n", p); 389 goto done; 390 } 391 tried = boot(mp, flag, file); 392 } 393 done: 394 if(tried == 0 && mode != Manual){ 395 flag = Fany; 396 if(mode == Mlocal) 397 flag &= ~Fbootp; 398 if(options & Snotflash) 399 flag &= ~Fflash; 400 if((mp = probe(Tany, flag, Dany)) != 0) 401 boot(mp, flag & mp->flag, 0); 402 } 403 404 def[0] = 0; 405 probe(Tany, Fnone, Dany); 406 407 flag = 0; 408 for(tp = types; tp->cname; tp++){ 409 for(mp = tp->media; mp; mp = mp->next){ 410 if(flag == 0){ 411 flag = 1; 412 print("Boot devices:"); 413 } 414 415 if(mp->flag & Fbootp) 416 print(" %s!%d", mp->type->name[Nbootp], mp->dev); 417 if(mp->flag & Fdos) 418 print(" %s!%d", mp->type->name[Ndos], mp->dev); 419 if(mp->flag & (Fflash|Fuart) || mp->flag & Fboot) 420 print(" %s!%d", mp->type->name[Nboot], mp->dev); 421 } 422 } 423 if(flag) 424 print("\n"); 425 426 for(;;){ 427 if(getstr("boot from", line, sizeof(line), def) >= 0){ 428 if(parse(line, &type, &flag, &dev, file)){ 429 if(mp = probe(type, flag, dev)) 430 boot(mp, flag, file); 431 } 432 } 433 def[0] = 0; 434 } 435 } 436 437 void 438 machinit(void) 439 { 440 memset(m, 0, sizeof(*m)); 441 m->delayloop = 20000; 442 m->cpupvr = getpvr(); 443 m->iomem = KADDR(INTMEM); 444 } 445 446 int 447 getcfields(char* lp, char** fields, int n, char* sep) 448 { 449 int i; 450 451 for(i = 0; lp && *lp && i < n; i++){ 452 while(*lp && strchr(sep, *lp) != 0) 453 *lp++ = 0; 454 if(*lp == 0) 455 break; 456 fields[i] = lp; 457 while(*lp && strchr(sep, *lp) == 0){ 458 if(*lp == '\\' && *(lp+1) == '\n') 459 *lp++ = ' '; 460 lp++; 461 } 462 } 463 464 return i; 465 } 466 467 static Map memv[512]; 468 static RMap rammap = {"physical memory"}; 469 470 void 471 meminit(void) 472 { 473 ulong e; 474 475 mapinit(&rammap, memv, sizeof(memv)); 476 e = PADDR(&end); 477 mapfree(&rammap, e, 4*1024*1024-e); /* fixed 4Mbytes is plenty for bootstrap */ 478 } 479 480 void* 481 ialloc(ulong n, int align) 482 { 483 ulong a; 484 int s; 485 486 if(align <= 0) 487 align = 4; 488 s = splhi(); 489 a = mapalloc(&rammap, 0, n, align); 490 splx(s); 491 if(a == 0) 492 panic("ialloc"); 493 return memset(KADDR(a), 0, n); 494 } 495 496 void* 497 malloc(ulong n) 498 { 499 ulong *p; 500 501 n = ((n+sizeof(int)-1)&~(sizeof(int)-1))+2*sizeof(int); 502 p = ialloc(n, sizeof(int)); 503 *p++ = 0xcafebeef; 504 *p++ = n; 505 return p; 506 } 507 508 void 509 free(void *ap) 510 { 511 int s; 512 ulong *p; 513 514 p = ap; 515 if(p){ 516 if(*(p -= 2) != 0xcafebeef) 517 panic("free"); 518 s = splhi(); 519 mapfree(&rammap, (ulong)p, p[1]); 520 splx(s); 521 } 522 } 523 524 void 525 sched(void) 526 { 527 } 528