load.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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. #include "sd.h"
  8. #include "fs.h"
  9. /*
  10. * "cache" must be in this list so that 9load will pass the definition of
  11. * the cache partition into the kernel so that the disk named by the `cfs'
  12. * variable in plan9.ini can be seen in all circumstances before termrc
  13. * sets up all the disk partitions. In particular, if it's on an odd-ball
  14. * disk like sd10 rather than sdC0, this is needed.
  15. */
  16. static char *diskparts[] = {
  17. "dos", "9fat", "fs", "data", "cdboot", "cache", 0
  18. };
  19. static char *etherparts[] = { "*", 0 };
  20. static char *diskinis[] = {
  21. "plan9/plan9.ini",
  22. "plan9.ini",
  23. 0
  24. };
  25. static char *etherinis[] = {
  26. "/cfg/pxe/%E",
  27. 0
  28. };
  29. /* ordering: devbios must be called before devsd calls sdbios */
  30. Type types[] = {
  31. { Tfloppy,
  32. Fini|Ffs,
  33. floppyinit, floppyinitdev,
  34. floppygetfspart, 0, floppyboot,
  35. floppyprintdevs,
  36. diskparts,
  37. diskinis,
  38. },
  39. { Tether,
  40. Fini|Fbootp,
  41. etherinit, etherinitdev,
  42. pxegetfspart, 0, bootpboot,
  43. etherprintdevs,
  44. etherparts,
  45. etherinis,
  46. },
  47. { Tbios,
  48. Fini|Ffs,
  49. biosinit, biosinitdev,
  50. biosgetfspart, nil, biosboot,
  51. biosprintdevs,
  52. diskparts,
  53. diskinis,
  54. },
  55. { Tcd,
  56. Fini|Ffs,
  57. cdinit, sdinitdev,
  58. sdgetfspart, sdaddconf, sdboot,
  59. sdprintdevs,
  60. diskparts,
  61. diskinis,
  62. },
  63. { Tsd,
  64. Fini|Ffs,
  65. sdinit, sdinitdev,
  66. sdgetfspart, sdaddconf, sdboot,
  67. sdprintdevs,
  68. diskparts,
  69. diskinis,
  70. },
  71. { Tnil,
  72. 0,
  73. nil, nil, nil, nil, nil, nil,
  74. nil,
  75. nil,
  76. 0,
  77. nil,
  78. },
  79. };
  80. static char *typenm[] = {
  81. [Tnil] "nil",
  82. [Tfloppy] "floppy",
  83. [Tsd] "sd",
  84. [Tether] "ether",
  85. [Tcd] "cd",
  86. [Tbios] "bios",
  87. };
  88. extern SDifc sdataifc;
  89. extern SDifc sdiahciifc;
  90. extern SDifc sdaoeifc;
  91. extern SDifc sdbiosifc;
  92. #ifndef NOSCSI
  93. extern SDifc sdmylexifc;
  94. extern SDifc sd53c8xxifc;
  95. #endif NOSCSI
  96. SDifc* sdifc[] = {
  97. &sdataifc,
  98. &sdiahciifc,
  99. #ifndef NOSCSI
  100. &sdmylexifc,
  101. &sd53c8xxifc,
  102. #endif
  103. &sdbiosifc,
  104. &sdaoeifc,
  105. nil,
  106. };
  107. typedef struct Mode Mode;
  108. enum {
  109. Maxdev = 7,
  110. Dany = -1,
  111. Nmedia = 16,
  112. Nini = 10,
  113. };
  114. enum { /* mode */
  115. Mauto = 0x00,
  116. Mlocal = 0x01,
  117. Manual = 0x02,
  118. NMode = 0x03,
  119. };
  120. typedef struct Medium Medium;
  121. struct Medium {
  122. Type* type;
  123. int flag;
  124. int dev;
  125. char name[NAMELEN];
  126. Fs *inifs;
  127. char *part;
  128. char *ini;
  129. Medium* next;
  130. };
  131. typedef struct Mode {
  132. char* name;
  133. int mode;
  134. } Mode;
  135. static Medium media[Nmedia];
  136. static Medium *curmedium = media;
  137. static Mode modes[NMode+1] = {
  138. [Mauto] { "auto", Mauto, },
  139. [Mlocal] { "local", Mlocal, },
  140. [Manual] { "manual", Manual, },
  141. };
  142. char **ini;
  143. int scsi0port;
  144. char *defaultpartition;
  145. int iniread;
  146. int debugload;
  147. int vga;
  148. char *persist;
  149. static char *
  150. typename(int type)
  151. {
  152. if (type < 0 || type >= nelem(typenm) || typenm[type] == nil)
  153. return "**gok**";
  154. return typenm[type];
  155. }
  156. static Medium*
  157. parse(char *line, char **file)
  158. {
  159. char *p;
  160. Type *tp;
  161. Medium *mp;
  162. if(p = strchr(line, '!')) {
  163. *p++ = 0;
  164. *file = p;
  165. } else
  166. *file = "";
  167. for(tp = types; tp->type != Tnil; tp++)
  168. for(mp = tp->media; mp; mp = mp->next)
  169. if(strcmp(mp->name, line) == 0)
  170. return mp;
  171. if(p)
  172. *--p = '!';
  173. return nil;
  174. }
  175. static int
  176. boot(Medium *mp, char *file)
  177. {
  178. Type *tp;
  179. Medium *xmp;
  180. static int didaddconf;
  181. Boot b;
  182. memset(&b, 0, sizeof b);
  183. b.state = INITKERNEL;
  184. if(didaddconf == 0) {
  185. didaddconf = 1;
  186. for(tp = types; tp->type != Tnil; tp++)
  187. if(tp->addconf)
  188. for(xmp = tp->media; xmp; xmp = xmp->next)
  189. (*tp->addconf)(xmp->dev);
  190. }
  191. sprint(BOOTLINE, "%s!%s", mp->name, file);
  192. // print("booting %s!%s\n", mp->name, file);
  193. return (*mp->type->boot)(mp->dev, file, &b);
  194. }
  195. static Medium*
  196. allocm(Type *tp)
  197. {
  198. Medium **l;
  199. if(curmedium >= &media[Nmedia])
  200. return 0;
  201. for(l = &tp->media; *l; l = &(*l)->next)
  202. ;
  203. *l = curmedium++;
  204. return *l;
  205. }
  206. Medium*
  207. probe(int type, int flag, int dev)
  208. {
  209. Type *tp;
  210. int i;
  211. Medium *mp;
  212. File f;
  213. Fs *fs;
  214. char **partp;
  215. for(tp = types; tp->type != Tnil; tp++){
  216. if(type != Tany && type != tp->type)
  217. continue;
  218. if(flag != Fnone){
  219. for(mp = tp->media; mp; mp = mp->next){
  220. if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
  221. return mp;
  222. }
  223. }
  224. if (debugload)
  225. print("probing %s...", typename(tp->type));
  226. if((tp->flag & Fprobe) == 0){
  227. tp->flag |= Fprobe;
  228. tp->mask = (*tp->init)();
  229. }
  230. for(i = 0; tp->mask; i++){
  231. if((tp->mask & (1<<i)) == 0)
  232. continue;
  233. tp->mask &= ~(1<<i);
  234. if((mp = allocm(tp)) == 0)
  235. continue;
  236. mp->dev = i;
  237. mp->flag = tp->flag;
  238. mp->type = tp;
  239. (*tp->initdev)(i, mp->name);
  240. if(mp->flag & Fini){
  241. mp->flag &= ~Fini;
  242. for(partp = tp->parts; *partp; partp++){
  243. if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
  244. continue;
  245. for(ini = tp->inis; *ini; ini++){
  246. if(fswalk(fs, *ini, &f) > 0){
  247. mp->inifs = fs;
  248. mp->part = *partp;
  249. mp->ini = f.path;
  250. mp->flag |= Fini;
  251. goto Break2;
  252. }
  253. }
  254. }
  255. }
  256. Break2:
  257. if((flag & mp->flag) && (dev == Dany || dev == i))
  258. return mp;
  259. }
  260. }
  261. return 0;
  262. }
  263. void
  264. main(void)
  265. {
  266. Medium *mp;
  267. int flag, i, mode, tried;
  268. char def[2*NAMELEN], line[80], *p, *file;
  269. Type *tp;
  270. i8042a20();
  271. memset(m, 0, sizeof(Mach));
  272. trapinit();
  273. clockinit();
  274. alarminit();
  275. meminit(0);
  276. spllo();
  277. /*
  278. * the soekris machines have no video but each has a serial port.
  279. * they must see serial output, if any, before cga output because
  280. * otherwise the soekris bios will translate cga output to serial
  281. * output, which will garble serial console output.
  282. */
  283. pcimatch(nil, 0, 0); /* force scan of pci table */
  284. if (!vga) {
  285. consinit("0", "9600"); /* e.g., for soekris debugging */
  286. print("Plan 9 Bootstrap (serial console)\n");
  287. }
  288. kbdinit();
  289. if((ulong)&end > (KZERO|(640*1024)))
  290. panic("i'm too big");
  291. if (debug)
  292. print("initial probe, for plan9.ini...");
  293. /* find and read plan9.ini, setting configuration variables */
  294. for(tp = types; tp->type != Tnil; tp++){
  295. /* skip bios until we have read plan9.ini */
  296. if(!pxe && tp->type == Tether || tp->type == Tbios)
  297. continue;
  298. if (debug)
  299. print("probing %s...", typename(tp->type));
  300. if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
  301. if (debug)
  302. print("using %s!%s!%s\n",
  303. mp->name, mp->part, mp->ini);
  304. iniread = !dotini(mp->inifs);
  305. break;
  306. }
  307. }
  308. if (debug)
  309. print("\n");
  310. /*
  311. * we should now have read plan9.ini, if any.
  312. */
  313. persist = getconf("*bootppersist");
  314. debugload = getconf("*debugload") != nil;
  315. if((p = getconf("console")) != nil)
  316. consinit(p, getconf("baud"));
  317. prcpuid();
  318. readlsconf();
  319. apminit();
  320. devpccardlink();
  321. devi82365link();
  322. /*
  323. * Even after we find the ini file, we keep probing disks,
  324. * because we have to collect the partition tables and
  325. * have boot devices for parse.
  326. */
  327. probe(Tany, Fnone, Dany);
  328. if (debugload)
  329. print("end disk probe\n");
  330. tried = 0;
  331. mode = Mauto;
  332. p = getconf("bootfile");
  333. if(p != 0) {
  334. mode = Manual;
  335. for(i = 0; i < NMode; i++){
  336. if(strcmp(p, modes[i].name) == 0){
  337. mode = modes[i].mode;
  338. goto done;
  339. }
  340. }
  341. if((mp = parse(p, &file)) == nil) {
  342. print("Unknown boot device: %s\n", p);
  343. goto done;
  344. }
  345. tried = boot(mp, file);
  346. }
  347. done:
  348. if(tried == 0 && mode != Manual){
  349. flag = Fany;
  350. if(mode == Mlocal)
  351. flag &= ~Fbootp;
  352. if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
  353. boot(mp, "");
  354. if (debugload)
  355. print("end auto probe\n");
  356. }
  357. def[0] = 0;
  358. probe(Tany, Fnone, Dany);
  359. if (debugload)
  360. print("end final probe\n");
  361. if(p = getconf("bootdef"))
  362. strcpy(def, p);
  363. flag = 0;
  364. for(tp = types; tp->type != Tnil; tp++){
  365. for(mp = tp->media; mp; mp = mp->next){
  366. if(flag == 0){
  367. flag = 1;
  368. print("Boot devices:");
  369. }
  370. (*tp->printdevs)(mp->dev);
  371. }
  372. }
  373. if(flag)
  374. print("\n");
  375. /*
  376. * e.g., *bootppersist=ether0
  377. *
  378. * previously, we looped in bootpopen if we were pxeload or if
  379. * *bootppersist was set. that doesn't work well for pxeload where
  380. * bootp will never succeed on the first interface but only on another
  381. * interface.
  382. */
  383. if (mode == Mauto && persist != nil &&
  384. (mp = parse(persist, &file)) != nil) {
  385. boot(mp, file);
  386. print("pausing before retry...");
  387. delay(30*1000);
  388. print("\n");
  389. }
  390. for(;;){
  391. if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
  392. if(mp = parse(line, &file))
  393. boot(mp, file);
  394. def[0] = 0;
  395. }
  396. }
  397. int
  398. getfields(char *lp, char **fields, int n, char sep)
  399. {
  400. int i;
  401. for(i = 0; lp && *lp && i < n; i++){
  402. while(*lp == sep)
  403. *lp++ = 0;
  404. if(*lp == 0)
  405. break;
  406. fields[i] = lp;
  407. while(*lp && *lp != sep){
  408. if(*lp == '\\' && *(lp+1) == '\n')
  409. *lp++ = ' ';
  410. lp++;
  411. }
  412. }
  413. return i;
  414. }
  415. int
  416. cistrcmp(char *a, char *b)
  417. {
  418. int ac, bc;
  419. for(;;){
  420. ac = *a++;
  421. bc = *b++;
  422. if(ac >= 'A' && ac <= 'Z')
  423. ac = 'a' + (ac - 'A');
  424. if(bc >= 'A' && bc <= 'Z')
  425. bc = 'a' + (bc - 'A');
  426. ac -= bc;
  427. if(ac)
  428. return ac;
  429. if(bc == 0)
  430. break;
  431. }
  432. return 0;
  433. }
  434. int
  435. cistrncmp(char *a, char *b, int n)
  436. {
  437. unsigned ac, bc;
  438. while(n > 0){
  439. ac = *a++;
  440. bc = *b++;
  441. n--;
  442. if(ac >= 'A' && ac <= 'Z')
  443. ac = 'a' + (ac - 'A');
  444. if(bc >= 'A' && bc <= 'Z')
  445. bc = 'a' + (bc - 'A');
  446. ac -= bc;
  447. if(ac)
  448. return ac;
  449. if(bc == 0)
  450. break;
  451. }
  452. return 0;
  453. }
  454. #define PSTART ( 8*1024*1024)
  455. #define PEND (16*1024*1024)
  456. ulong palloc = PSTART;
  457. void*
  458. ialloc(ulong n, int align)
  459. {
  460. ulong p;
  461. int a;
  462. p = palloc;
  463. if(align <= 0)
  464. align = 4;
  465. if(a = n % align)
  466. n += align - a;
  467. if(a = p % align)
  468. p += align - a;
  469. palloc = p+n;
  470. if(palloc > PEND)
  471. panic("ialloc(%lud, %d) called from %#p",
  472. n, align, getcallerpc(&n));
  473. return memset((void*)(p|KZERO), 0, n);
  474. }
  475. void*
  476. xspanalloc(ulong size, int align, ulong span)
  477. {
  478. ulong a, v;
  479. if((palloc + (size+align+span)) > PEND)
  480. panic("xspanalloc(%lud, %d, 0x%lux) called from %#p",
  481. size, align, span, getcallerpc(&size));
  482. a = (ulong)ialloc(size+align+span, 0);
  483. if(span > 2)
  484. v = (a + span) & ~(span-1);
  485. else
  486. v = a;
  487. if(align > 1)
  488. v = (v + align) & ~(align-1);
  489. return (void*)v;
  490. }
  491. static Block *allocbp;
  492. Block*
  493. allocb(int size)
  494. {
  495. Block *bp, **lbp;
  496. ulong addr;
  497. lbp = &allocbp;
  498. for(bp = *lbp; bp; bp = bp->next){
  499. if((bp->lim - bp->base) >= size){
  500. *lbp = bp->next;
  501. break;
  502. }
  503. lbp = &bp->next;
  504. }
  505. if(bp == 0){
  506. if((palloc + (sizeof(Block)+size+64)) > PEND)
  507. panic("allocb(%d) called from %#p",
  508. size, getcallerpc(&size));
  509. bp = ialloc(sizeof(Block)+size+64, 0);
  510. addr = (ulong)bp;
  511. addr = ROUNDUP(addr + sizeof(Block), 8);
  512. bp->base = (uchar*)addr;
  513. bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
  514. }
  515. if(bp->flag)
  516. panic("allocb reuse");
  517. bp->rp = bp->base;
  518. bp->wp = bp->rp;
  519. bp->next = 0;
  520. bp->flag = 1;
  521. return bp;
  522. }
  523. void
  524. freeb(Block* bp)
  525. {
  526. bp->next = allocbp;
  527. allocbp = bp;
  528. bp->flag = 0;
  529. }
  530. enum {
  531. Paddr= 0x70, /* address port */
  532. Pdata= 0x71, /* data port */
  533. };
  534. uchar
  535. nvramread(int offset)
  536. {
  537. outb(Paddr, offset);
  538. return inb(Pdata);
  539. }
  540. void (*etherdetach)(void);
  541. void (*floppydetach)(void);
  542. void (*sddetach)(void);
  543. void
  544. warp9(ulong entry)
  545. {
  546. if(etherdetach)
  547. etherdetach();
  548. if(floppydetach)
  549. floppydetach();
  550. if(sddetach)
  551. sddetach();
  552. consdrain();
  553. splhi();
  554. trapdisable();
  555. /*
  556. * This is where to push things on the stack to
  557. * boot *BSD systems, e.g.
  558. (*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
  559. * will enable NetBSD boot (the real memory size needs to
  560. * go in the 5th argument).
  561. */
  562. (*(void(*)(void))(PADDR(entry)))();
  563. }