load.c 11 KB

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