load.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "fs.h"
  16. Mach* m;
  17. uint32_t* mach0pdb;
  18. Mach* mach0m;
  19. Segdesc* mach0gdt;
  20. uint32_t memstart;
  21. uint32_t memend;
  22. int vflag = 0;
  23. int debug = 0;
  24. static char *diskparts[] = { "dos", "9fat", "fs", "data", "cdboot", 0 };
  25. static char *etherparts[] = { "*", 0 };
  26. static char *diskinis[] = {
  27. "plan9/plan9.ini",
  28. "plan9.ini",
  29. 0
  30. };
  31. static char *etherinis[] = {
  32. "/cfg/pxe/%E",
  33. 0
  34. };
  35. #define NODISCS
  36. Type types[] = {
  37. { Tfloppy,
  38. Fini|Ffs,
  39. floppyinit, floppyinitdev,
  40. floppygetfspart, 0, floppyboot,
  41. floppyprintdevs,
  42. diskparts,
  43. diskinis,
  44. },
  45. #ifndef NODISCS
  46. { Tcd,
  47. Fini|Ffs,
  48. cdinit, sdinitdev,
  49. sdgetfspart, sdaddconf, sdboot,
  50. sdprintdevs,
  51. diskparts,
  52. diskinis,
  53. },
  54. #endif /* NODISCS */
  55. { Tether,
  56. Fini|Fbootp,
  57. etherinit, etherinitdev,
  58. pxegetfspart, 0, bootpboot,
  59. etherprintdevs,
  60. etherparts,
  61. etherinis,
  62. },
  63. #ifndef NODISCS
  64. { Tsd,
  65. Fini|Ffs,
  66. sdinit, sdinitdev,
  67. sdgetfspart, sdaddconf, sdboot,
  68. sdprintdevs,
  69. diskparts,
  70. diskinis,
  71. },
  72. #endif /* NODISCS */
  73. { Tnil,
  74. 0,
  75. nil, nil, nil, nil, nil, nil,
  76. nil,
  77. nil,
  78. 0,
  79. nil,
  80. },
  81. };
  82. #ifndef NODISCS
  83. #include "sd.h"
  84. extern SDifc sdataifc;
  85. #ifdef NOSCSI
  86. SDifc* sdifc[] = {
  87. &sdataifc,
  88. nil,
  89. };
  90. #else
  91. extern SDifc sdmylexifc;
  92. extern SDifc sd53c8xxifc;
  93. SDifc* sdifc[] = {
  94. &sdataifc,
  95. &sdmylexifc,
  96. &sd53c8xxifc,
  97. nil,
  98. };
  99. #endif NOSCSI
  100. #endif /* NODISCS */
  101. typedef struct Mode Mode;
  102. enum {
  103. Maxdev = 7,
  104. Dany = -1,
  105. Nmedia = 16,
  106. Nini = 10,
  107. };
  108. enum { /* mode */
  109. Mauto = 0x00,
  110. Mlocal = 0x01,
  111. Manual = 0x02,
  112. NMode = 0x03,
  113. };
  114. typedef struct Medium Medium;
  115. struct Medium {
  116. Type* type;
  117. int flag;
  118. int dev;
  119. char name[NAMELEN];
  120. Fs *inifs;
  121. char *part;
  122. char *ini;
  123. Medium* next;
  124. };
  125. typedef struct Mode {
  126. char* name;
  127. int mode;
  128. } Mode;
  129. static Medium media[Nmedia];
  130. static Medium *curmedium = media;
  131. static Mode modes[NMode+1] = {
  132. [Mauto] { "auto", Mauto, },
  133. [Mlocal] { "local", Mlocal, },
  134. [Manual] { "manual", Manual, },
  135. };
  136. char **ini;
  137. int scsi0port;
  138. char *defaultpartition;
  139. int iniread;
  140. static Medium*
  141. parse(char *line, char **file)
  142. {
  143. char *p;
  144. Type *tp;
  145. Medium *mp;
  146. if(p = strchr(line, '!')) {
  147. *p++ = 0;
  148. *file = p;
  149. } else
  150. *file = "";
  151. for(tp = types; tp->type != Tnil; tp++)
  152. for(mp = tp->media; mp; mp = mp->next)
  153. if(strcmp(mp->name, line) == 0)
  154. return mp;
  155. if(p)
  156. *--p = '!';
  157. return nil;
  158. }
  159. static int
  160. boot(Medium *mp, char *file)
  161. {
  162. Type *tp;
  163. Medium *xmp;
  164. static int didaddconf;
  165. Boot b;
  166. char *p;
  167. memset(&b, 0, sizeof b);
  168. b.state = INITKERNEL;
  169. if(didaddconf == 0) {
  170. didaddconf = 1;
  171. for(tp = types; tp->type != Tnil; tp++)
  172. if(tp->addconf)
  173. for(xmp = tp->media; xmp; xmp = xmp->next)
  174. (*tp->addconf)(xmp->dev);
  175. }
  176. sprint(BOOTLINE, "%s!%s", mp->name, file);
  177. for(p = file; *p != '\0'; p++){
  178. if(*p != ' ' && *p != '\t')
  179. continue;
  180. *p = '\0';
  181. break;
  182. }
  183. return (*mp->type->boot)(mp->dev, file, &b);
  184. }
  185. static Medium*
  186. allocm(Type *tp)
  187. {
  188. Medium **l;
  189. if(curmedium >= &media[Nmedia])
  190. return 0;
  191. for(l = &tp->media; *l; l = &(*l)->next)
  192. ;
  193. *l = curmedium++;
  194. return *l;
  195. }
  196. Medium*
  197. probe(int type, int flag, int dev)
  198. {
  199. Type *tp;
  200. int i;
  201. Medium *mp;
  202. File f;
  203. Fs *fs;
  204. char **partp;
  205. for(tp = types; tp->type != Tnil; tp++){
  206. if(type != Tany && type != tp->type)
  207. continue;
  208. if(flag != Fnone){
  209. for(mp = tp->media; mp; mp = mp->next){
  210. if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
  211. return mp;
  212. }
  213. }
  214. if((tp->flag & Fprobe) == 0){
  215. tp->flag |= Fprobe;
  216. tp->mask = (*tp->init)();
  217. }
  218. for(i = 0; tp->mask; i++){
  219. if((tp->mask & (1<<i)) == 0)
  220. continue;
  221. tp->mask &= ~(1<<i);
  222. if((mp = allocm(tp)) == 0)
  223. continue;
  224. mp->dev = i;
  225. mp->flag = tp->flag;
  226. mp->type = tp;
  227. (*tp->initdev)(i, mp->name);
  228. if(mp->flag & Fini){
  229. mp->flag &= ~Fini;
  230. for(partp = tp->parts; *partp; partp++){
  231. if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
  232. continue;
  233. for(ini = tp->inis; *ini; ini++){
  234. if(fswalk(fs, *ini, &f) > 0){
  235. mp->inifs = fs;
  236. mp->part = *partp;
  237. mp->ini = f.path;
  238. mp->flag |= Fini;
  239. goto Break2;
  240. }
  241. }
  242. }
  243. }
  244. Break2:
  245. if((flag & mp->flag) && (dev == Dany || dev == i))
  246. return mp;
  247. }
  248. }
  249. return 0;
  250. }
  251. void
  252. main(void)
  253. {
  254. Medium *mp;
  255. int cons, flag, i, mode, tried;
  256. char def[2*NAMELEN], line[80], *p, *file;
  257. Type *tp;
  258. i8042a20();
  259. cgapost(0x9B);
  260. memset(m, 0, sizeof(Mach));
  261. m->pdb = mach0pdb;
  262. m->gdt = mach0gdt;
  263. /*
  264. * Memstart is set by the low-level bootstrap
  265. * code to the first free memory location after
  266. * text+data+bss+conf+pdb+pt+pmach+vmach+gdt.
  267. * This is where allocatable memory starts.
  268. * However, the E820 map indicates 0x000A0000
  269. * is UPA memory although the VGA memory is
  270. * probably there and meminit will get that wrong.
  271. * Hacks are needed to make this work until it
  272. * is all rewritten.
  273. * Memstart->memend could be memstart->KZERO|0x9xxxx
  274. * to keep all the memory use below 1MiB.
  275. *
  276. * Sigh. Accomodate the bloated Plan 9 kernel to prevent
  277. * having different PXE loaders for different systems.
  278. memstart = KZERO|(3*MiB+512*KiB);
  279. memend = KZERO|(4*MiB);
  280. */
  281. memstart = KZERO|(8*MiB);
  282. memend = KZERO|(16*MiB);
  283. cgainit();
  284. trapinit();
  285. clockinit();
  286. alarminit();
  287. spllo();
  288. kbdinit();
  289. cons = consinit("0", 0);
  290. readlsconf();
  291. meminit(0);
  292. if(end > KADDR(640*1024))
  293. panic("i'm too big\n");
  294. for(tp = types; tp->type != Tnil; tp++){
  295. //if(tp->type == Tether)
  296. // continue;
  297. if((mp = probe(tp->type, Fini, Dany)) && (mp->flag & Fini)){
  298. print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
  299. iniread = !dotini(mp->inifs);
  300. break;
  301. }
  302. }
  303. apminit();
  304. if(iniread && !cons && (p = getconf("console")) != nil)
  305. cons = consinit(p, getconf("baud"));
  306. USED(cons);
  307. //devpccardlink();
  308. //devi82365link();
  309. if(vflag){
  310. pcihinv(nil);
  311. delay(5000);
  312. }
  313. /*
  314. * Even after we find the ini file, we keep probing disks,
  315. * because we have to collect the partition tables and
  316. * have boot devices for parse.
  317. */
  318. probe(Tany, Fnone, Dany);
  319. tried = 0;
  320. mode = Mauto;
  321. p = getconf("bootfile");
  322. if(p != 0) {
  323. strecpy(line, line+sizeof(line), p);
  324. p = line;
  325. mode = Manual;
  326. for(i = 0; i < NMode; i++){
  327. if(strcmp(p, modes[i].name) == 0){
  328. mode = modes[i].mode;
  329. goto done;
  330. }
  331. }
  332. if((mp = parse(p, &file)) == nil) {
  333. print("Unknown boot device: %s\n", p);
  334. goto done;
  335. }
  336. tried = boot(mp, file);
  337. }
  338. done:
  339. if(tried == 0 && mode != Manual){
  340. flag = Fany;
  341. if(mode == Mlocal)
  342. flag &= ~Fbootp;
  343. if((mp = probe(Tany, flag, Dany)) && mp->type->type != Tfloppy)
  344. boot(mp, "");
  345. }
  346. def[0] = 0;
  347. probe(Tany, Fnone, Dany);
  348. if(p = getconf("bootdef"))
  349. strecpy(def, def+sizeof(def), p);
  350. flag = 0;
  351. for(tp = types; tp->type != Tnil; tp++){
  352. for(mp = tp->media; mp; mp = mp->next){
  353. if(flag == 0){
  354. flag = 1;
  355. print("Boot devices:");
  356. }
  357. (*tp->printdevs)(mp->dev);
  358. }
  359. }
  360. if(flag)
  361. print("\n");
  362. for(;;){
  363. if(getstr("boot from", line, sizeof(line), def, (mode != Manual)*15) >= 0)
  364. if(mp = parse(line, &file))
  365. boot(mp, file);
  366. def[0] = 0;
  367. }
  368. }
  369. int
  370. getfields(char *lp, char **fields, int n, char sep)
  371. {
  372. int i;
  373. for(i = 0; lp && *lp && i < n; i++){
  374. while(*lp == sep)
  375. *lp++ = 0;
  376. if(*lp == 0)
  377. break;
  378. fields[i] = lp;
  379. while(*lp && *lp != sep){
  380. if(*lp == '\\' && *(lp+1) == '\n')
  381. *lp++ = ' ';
  382. lp++;
  383. }
  384. }
  385. return i;
  386. }
  387. int
  388. cistrcmp(char *a, char *b)
  389. {
  390. int ac, bc;
  391. for(;;){
  392. ac = *a++;
  393. bc = *b++;
  394. if(ac >= 'A' && ac <= 'Z')
  395. ac = 'a' + (ac - 'A');
  396. if(bc >= 'A' && bc <= 'Z')
  397. bc = 'a' + (bc - 'A');
  398. ac -= bc;
  399. if(ac)
  400. return ac;
  401. if(bc == 0)
  402. break;
  403. }
  404. return 0;
  405. }
  406. int
  407. cistrncmp(char *a, char *b, int n)
  408. {
  409. unsigned ac, bc;
  410. while(n > 0){
  411. ac = *a++;
  412. bc = *b++;
  413. n--;
  414. if(ac >= 'A' && ac <= 'Z')
  415. ac = 'a' + (ac - 'A');
  416. if(bc >= 'A' && bc <= 'Z')
  417. bc = 'a' + (bc - 'A');
  418. ac -= bc;
  419. if(ac)
  420. return ac;
  421. if(bc == 0)
  422. break;
  423. }
  424. return 0;
  425. }
  426. uint32_t palloc = 0;
  427. void*
  428. ialloc(uint32_t n, int align)
  429. {
  430. uint32_t p;
  431. int a;
  432. if(palloc == 0)
  433. palloc = memstart;
  434. p = palloc;
  435. if(align <= 0)
  436. align = 4;
  437. if(a = n % align)
  438. n += align - a;
  439. if(a = p % align)
  440. p += align - a;
  441. palloc = p+n;
  442. if(palloc > memend)
  443. panic("ialloc(%lud, %d) called from 0x%lux\n",
  444. n, align, getcallerpc());
  445. return memset((void*)p, 0, n);
  446. }
  447. void*
  448. xspanalloc(uint32_t size, int align, uint32_t span)
  449. {
  450. uint32_t a, v;
  451. if((palloc + (size+align+span)) > memend)
  452. panic("xspanalloc(%lud, %d, 0x%lux) called from 0x%lux\n",
  453. size, align, span, getcallerpc());
  454. a = (uint32_t)ialloc(size+align+span, 0);
  455. if(span > 2)
  456. v = (a + span) & ~(span-1);
  457. else
  458. v = a;
  459. if(align > 1)
  460. v = (v + align) & ~(align-1);
  461. return (void*)v;
  462. }
  463. static Block *allocbp;
  464. Block*
  465. allocb(int size)
  466. {
  467. Block *bp, **lbp;
  468. uint32_t addr;
  469. lbp = &allocbp;
  470. for(bp = *lbp; bp; bp = bp->next){
  471. if((bp->lim - bp->base) >= size){
  472. *lbp = bp->next;
  473. break;
  474. }
  475. lbp = &bp->next;
  476. }
  477. if(bp == 0){
  478. if((palloc + (sizeof(Block)+size+64)) > memend)
  479. panic("allocb(%d) called from 0x%lux\n",
  480. size, getcallerpc());
  481. bp = ialloc(sizeof(Block)+size+64, 0);
  482. addr = (uint32_t)bp;
  483. addr = ROUNDUP(addr + sizeof(Block), 8);
  484. bp->base = (uint8_t*)addr;
  485. bp->lim = ((uint8_t*)bp) + sizeof(Block)+size+64;
  486. }
  487. if(bp->flag)
  488. panic("allocb reuse\n");
  489. bp->rp = bp->base;
  490. bp->wp = bp->rp;
  491. bp->next = 0;
  492. bp->flag = 1;
  493. return bp;
  494. }
  495. void
  496. freeb(Block* bp)
  497. {
  498. bp->next = allocbp;
  499. allocbp = bp;
  500. bp->flag = 0;
  501. }
  502. enum {
  503. Paddr= 0x70, /* address port */
  504. Pdata= 0x71, /* data port */
  505. };
  506. uint8_t
  507. nvramread(int offset)
  508. {
  509. outb(Paddr, offset);
  510. return inb(Pdata);
  511. }
  512. void (*etherdetach)(void);
  513. void (*floppydetach)(void);
  514. void (*sddetach)(void);
  515. void
  516. impulse(void)
  517. {
  518. if(etherdetach)
  519. etherdetach();
  520. if(floppydetach)
  521. floppydetach();
  522. if(sddetach)
  523. sddetach();
  524. consdrain();
  525. trapdisable();
  526. }
  527. void
  528. warp9(uint32_t entry)
  529. {
  530. extern void _warp9(uint32_t);
  531. print("warp9(%#lux) %d\n", entry, nmmap);
  532. if(vflag)
  533. print("mkmultiboot\n");
  534. mkmultiboot();
  535. if(vflag)
  536. print("impulse\n");
  537. /*
  538. * No output after impulse().
  539. */
  540. impulse();
  541. _warp9(PADDR(entry));
  542. /*
  543. * Instead, this is where to push things on the stack to
  544. * boot *BSD systems, e.g.
  545. (*(void(*)(void*, void*, void*, void*, ulong, ulong))(PADDR(entry)))(0, 0, 0, 0, 8196, 640);
  546. * will enable NetBSD boot (the real memory size needs to
  547. * go in the 5th argument).
  548. (*(void(*)(void))(PADDR(entry)))();
  549. */
  550. }