disk.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /*
  2. * aboot/disk.c
  3. *
  4. * This file is part of aboot, the SRM bootloader for Linux/Alpha
  5. * Copyright (C) 1996 Linus Torvalds, David Mosberger, and Michael Schwingen.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of the
  10. * License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. #ifdef TESTING
  22. # include <stdlib.h>
  23. # include <stdio.h>
  24. # include <fcntl.h>
  25. # include <unistd.h>
  26. #endif
  27. #include "config.h"
  28. #include "aboot.h"
  29. #include "bootfs.h"
  30. #include "cons.h"
  31. #include "disklabel.h"
  32. #include "utils.h"
  33. #include "string.h"
  34. #include <linux/elf.h>
  35. #include <asm/console.h>
  36. #include "system.h"
  37. extern struct bootfs ext2fs;
  38. extern struct bootfs iso;
  39. extern struct bootfs ufs;
  40. extern struct bootfs dummyfs;
  41. struct disklabel * label;
  42. int boot_part = -1;
  43. static struct bootfs *bootfs[] = {
  44. &ext2fs,
  45. &iso,
  46. &ufs
  47. };
  48. /*
  49. * Attempt a "raw" boot (uncompressed ELF kernel follows right after aboot).
  50. *
  51. * This will eventually be rewritten to accept compressed kernels
  52. * (along with net_aboot). It should also be merged with the other
  53. * load methods as there is some code duplication here we don't want.
  54. */
  55. int
  56. load_raw (long dev)
  57. {
  58. extern char _end;
  59. char *buf;
  60. long aboot_size = &_end - (char *) BOOT_ADDR;
  61. long ksect = (aboot_size + SECT_SIZE - 1) / SECT_SIZE + BOOT_SECTOR;
  62. long nread;
  63. int i;
  64. printf("aboot: loading kernel from boot sectors...\n");
  65. /* We only need the program headers so this should be fine */
  66. buf = malloc(SECT_SIZE);
  67. /* Read ELF headers: */
  68. nread = cons_read(dev, buf, SECT_SIZE, ksect * SECT_SIZE);
  69. if (nread != SECT_SIZE) {
  70. printf("aboot: read returned %ld instead of %ld bytes\n",
  71. nread, (long) SECT_SIZE);
  72. return -1;
  73. }
  74. if (first_block(buf, SECT_SIZE) < 0) {
  75. return -1;
  76. }
  77. for (i = 0; i < nchunks; ++i) {
  78. char *dest;
  79. printf("aboot: segment %d, %ld bytes at %#lx\n", i, chunks[i].size,
  80. chunks[i].addr);
  81. #ifdef TESTING
  82. dest = malloc(chunks[i].size);
  83. #else
  84. dest = (char *) chunks[i].addr;
  85. #endif
  86. nread = cons_read(dev, dest, chunks[i].size,
  87. chunks[i].offset + ksect * SECT_SIZE);
  88. if (nread != chunks[i].size) {
  89. printf("aboot: read returned %ld instead of %ld bytes\n",
  90. nread, chunks[i].size);
  91. return -1;
  92. }
  93. }
  94. return 0;
  95. }
  96. int
  97. load_uncompressed (int fd)
  98. {
  99. long nread, nblocks;
  100. unsigned char *buf;
  101. int i;
  102. buf = malloc(bfs->blocksize);
  103. /* read ELF headers: */
  104. nread = (*bfs->bread)(fd, 0, 1, buf);
  105. if (nread != bfs->blocksize) {
  106. printf("aboot: read returned %ld instead of %ld bytes\n",
  107. nread, sizeof(buf));
  108. return -1;
  109. }
  110. #ifdef DEBUG
  111. {
  112. int i,j,c;
  113. for(i = 0; i < 16; i++) {
  114. for (j = 0; j < 16; j++)
  115. printf("%02X ", buf[j+16*i]);
  116. for(j = 0; j < 16; j++) {
  117. c = buf[j+16*i];
  118. printf("%c", (c >= ' ') ? c : ' ');
  119. }
  120. printf("\n");
  121. }
  122. }
  123. #endif
  124. if (first_block(buf, bfs->blocksize) < 0) {
  125. return -1;
  126. }
  127. /* read one segment at a time */
  128. for (i = 0; i < nchunks; ++i) {
  129. char *dest;
  130. /* include any unaligned bits of the offset */
  131. nblocks = (chunks[i].size + (chunks[i].offset & (bfs->blocksize - 1)) +
  132. bfs->blocksize - 1) / bfs->blocksize;
  133. printf("aboot: segment %d, %ld bytes at %#lx\n", i, chunks[i].size,
  134. chunks[i].addr);
  135. #ifdef TESTING
  136. dest = malloc(nblocks * bfs->blocksize);
  137. #else
  138. dest = (char *) chunks[i].addr;
  139. #endif
  140. nread = (*bfs->bread)(fd, chunks[i].offset / bfs->blocksize,
  141. nblocks, dest);
  142. if (nread != nblocks * bfs->blocksize) {
  143. printf("aboot: read returned %ld instead of %ld bytes\n",
  144. nread, nblocks * bfs->blocksize);
  145. return -1;
  146. }
  147. /* In practice, they will always be aligned */
  148. if ((chunks[i].offset & (bfs->blocksize - 1)) != 0)
  149. memmove(dest,
  150. dest + (chunks[i].offset & (bfs->blocksize - 1)),
  151. chunks[i].size);
  152. }
  153. return 0;
  154. }
  155. static long
  156. read_kernel (const char *filename)
  157. {
  158. volatile int attempt, method;
  159. long len;
  160. int fd;
  161. static struct {
  162. const char *name;
  163. int (*func)(int fd);
  164. } read_method[]= {
  165. {"uncompressed", load_uncompressed},
  166. {"compressed", uncompress_kernel}
  167. };
  168. long res;
  169. # define NUM_METHODS ((int)(sizeof(read_method)/sizeof(read_method[0])))
  170. #ifdef DEBUG
  171. printf("read_kernel(%s)\n", filename);
  172. #endif
  173. method = 0;
  174. len = strlen(filename);
  175. if (len > 3 && filename[len - 3] == '.'
  176. && filename[len - 2] == 'g' && filename[len - 1] == 'z')
  177. {
  178. /* if filename ends in .gz we don't try plain method: */
  179. method = 1;
  180. }
  181. for (attempt = 0; attempt < NUM_METHODS; ++attempt) {
  182. fd = (*bfs->open)(filename);
  183. if (fd < 0) {
  184. printf("%s: file not found\n", filename);
  185. return -1;
  186. }
  187. printf("aboot: loading %s %s...\n",
  188. read_method[method].name, filename);
  189. if (!_setjmp(jump_buffer)) {
  190. res = (*read_method[method].func)(fd);
  191. (*bfs->close)(fd);
  192. if (res >= 0) {
  193. return 0;
  194. }
  195. }
  196. method = (method + 1) % NUM_METHODS;
  197. }
  198. return -1;
  199. }
  200. long
  201. read_initrd()
  202. {
  203. int nblocks, nread, fd;
  204. struct stat buf;
  205. fd = (*bfs->open)(initrd_file);
  206. if (fd < 0) {
  207. printf("%s: file not found\n", initrd_file);
  208. return -1;
  209. }
  210. (*bfs->fstat)(fd, &buf);
  211. initrd_size = buf.st_size;
  212. #ifdef TESTING
  213. initrd_start = (unsigned long) malloc(initrd_size);
  214. #else
  215. /* put it as high up in memory as possible */
  216. if (!free_mem_ptr)
  217. free_mem_ptr = memory_end();
  218. /* page aligned (downward) */
  219. initrd_start = (free_mem_ptr - initrd_size) & ~(PAGE_SIZE-1);
  220. /* update free_mem_ptr so malloc() still works */
  221. free_mem_ptr = initrd_start;
  222. #endif
  223. nblocks = initrd_size / bfs->blocksize;
  224. printf("aboot: loading initrd (%ld bytes/%d blocks) at %#lx\n",
  225. initrd_size, nblocks, initrd_start);
  226. if (nblocks & (bfs->blocksize - 1)) nblocks++;
  227. nread = (*bfs->bread)(fd, 0, nblocks, (char*) initrd_start);
  228. if (nread != nblocks * bfs->blocksize) {
  229. printf("aboot: read returned %d instead of %d (%d*%d) bytes\n",
  230. nread, nblocks * bfs->blocksize,
  231. nblocks, bfs->blocksize);
  232. return -1;
  233. }
  234. return 0;
  235. }
  236. static void
  237. get_disklabel (long dev)
  238. {
  239. static char lsect[512];
  240. long nread;
  241. #ifdef DEBUG
  242. printf("load_label(dev=%lx)\n", dev);
  243. #endif
  244. nread = cons_read(dev, &lsect, LABELOFFSET + sizeof(*label),
  245. LABELSECTOR);
  246. if (nread != LABELOFFSET + sizeof(*label)) {
  247. printf("aboot: read of disklabel sector failed (nread=%ld)\n",
  248. nread);
  249. return;
  250. }
  251. label = (struct disklabel*) &lsect[LABELOFFSET];
  252. if (label->d_magic == DISKLABELMAGIC &&
  253. label->d_magic2 == DISKLABELMAGIC)
  254. {
  255. printf("aboot: valid disklabel found: %d partitions.\n",
  256. label->d_npartitions);
  257. } else {
  258. printf("aboot: no disklabel found.\n");
  259. label = 0;
  260. }
  261. }
  262. struct bootfs *
  263. mount_fs (long dev, int partition)
  264. {
  265. struct d_partition * part;
  266. struct bootfs * fs = 0;
  267. int i;
  268. #ifdef DEBUG
  269. printf("mount_fs(%lx, %d)\n", dev, partition);
  270. #endif
  271. if (partition == 0) {
  272. fs = &dummyfs;
  273. if ((*fs->mount)(dev, 0, 0) < 0) {
  274. printf("aboot: disk mount failed\n");
  275. return 0;
  276. }
  277. } else if (!label) {
  278. /* floppies and such, no disklabel */
  279. for (i = 0; i < (int)(sizeof(bootfs)/sizeof(bootfs[0])); ++i) {
  280. if ((*bootfs[i]->mount)(dev, 0, 1) >= 0) {
  281. fs = bootfs[i];
  282. break;
  283. }
  284. }
  285. if (!fs) {
  286. printf("aboot: unknown filesystem type\n");
  287. return 0;
  288. }
  289. } else {
  290. if ((unsigned) (partition - 1) >= label->d_npartitions) {
  291. printf("aboot: invalid partition %u\n", partition);
  292. return 0;
  293. }
  294. part = &label->d_partitions[partition - 1];
  295. for (i = 0; bootfs[i]->fs_type != part->p_fstype; ++i) {
  296. if (i + 1
  297. >= (int) (sizeof(bootfs)/sizeof(bootfs[0])))
  298. {
  299. printf("aboot: don't know how to mount "
  300. "partition %d (filesystem type %d)\n",
  301. partition, part->p_fstype);
  302. return 0;
  303. }
  304. }
  305. fs = bootfs[i];
  306. if ((*fs->mount)(dev, (long)(part->p_offset) * (long)(label->d_secsize), 0)
  307. < 0) {
  308. printf("aboot: mount of partition %d failed\n",
  309. partition);
  310. return 0;
  311. }
  312. }
  313. return fs;
  314. }
  315. void
  316. list_directory (struct bootfs *fs, char *dir)
  317. {
  318. int fd = (*fs->open)(dir);
  319. /* yes, our readdir() is not exactly like the real one */
  320. int rewind = 0;
  321. const char * ent;
  322. if (fd < 0) {
  323. printf("%s: directory not found\n", dir);
  324. return;
  325. }
  326. while ((ent = (*fs->readdir)(fd, !rewind++))) {
  327. printf("%s\n", ent);
  328. }
  329. (*fs->close)(fd);
  330. }
  331. int
  332. open_config_file(struct bootfs *fs)
  333. {
  334. static const char *configs[] = {
  335. "/etc/aboot.conf",
  336. "/aboot.conf",
  337. "/etc/aboot.cfg",
  338. "/aboot.cfg"
  339. };
  340. const int nconfigs = sizeof(configs) / sizeof(configs[0]);
  341. int i, fd = -1;
  342. for (i = 0; i < nconfigs; i++) {
  343. fd = (*fs->open)(configs[i]);
  344. if (fd >= 0)
  345. break;
  346. }
  347. return fd;
  348. }
  349. void
  350. print_config_file (struct bootfs *fs)
  351. {
  352. int fd, nread, blkno = 0;
  353. char *buf;
  354. fd = open_config_file(fs);
  355. if (fd < 0) {
  356. printf("%s: file not found\n", CONFIG_FILE);
  357. return;
  358. }
  359. buf = malloc(fs->blocksize + 1);
  360. if (!buf) {
  361. printf("aboot: malloc failed!\n");
  362. return;
  363. }
  364. do {
  365. nread = (*fs->bread)(fd, blkno++, 1, buf);
  366. buf[nread] = '\0';
  367. printf("%s", buf);
  368. } while (nread > 0);
  369. (*fs->close)(fd);
  370. }
  371. int
  372. get_default_args (struct bootfs *fs, char *str, int num)
  373. {
  374. int fd, nread, state, line, blkno = 0;
  375. char *buf, *d, *p;
  376. *str = '\0';
  377. fd = open_config_file(fs);
  378. if (fd < 0) {
  379. printf("%s: file not found\n", CONFIG_FILE);
  380. return -1;
  381. }
  382. buf = malloc(fs->blocksize);
  383. if (!buf) {
  384. printf("aboot: malloc failed!\n");
  385. return -1;
  386. }
  387. d = str;
  388. line = 1;
  389. state = 2;
  390. do {
  391. nread = (*fs->bread)(fd, blkno++, 1, buf);
  392. p = buf;
  393. while (p < buf + nread && *p && state != 5) {
  394. switch (state) {
  395. case 0: /* ignore rest of line */
  396. case 1: /* in comment */
  397. if (*p == '\n') state = 2;
  398. break;
  399. case 2: /* after end of line */
  400. line++;
  401. if (*p == num) {
  402. state = 3; /* found it... */
  403. break;
  404. }
  405. if (*p == '#') {
  406. state = 1; /* comment */
  407. break;
  408. }
  409. if (*p == '-') {
  410. state = 5; /* end-of-file mark */
  411. break;
  412. }
  413. state = 0; /* ignore rest of line */
  414. break;
  415. case 3: /* after matched number */
  416. if (*p == ':') {
  417. state = 4; /* copy string */
  418. } else {
  419. state = 2; /* ignore rest */
  420. printf("aboot: syntax error in line "
  421. "%d: `:' expected\n", line);
  422. }
  423. break;
  424. case 4: /* copy until EOL */
  425. if (*p == '\n') {
  426. *d = 0;
  427. state=5;
  428. } else {
  429. *d++ = *p;
  430. }
  431. break;
  432. default:
  433. break;
  434. }
  435. p++;
  436. }
  437. } while (nread > 0 && state != 5);
  438. (*fs->close)(fd);
  439. #ifdef DEBUG
  440. printf("get_default done\n");
  441. #endif
  442. if (state != 5) {
  443. printf("aboot: could not find default config `%c'\n", num);
  444. return -1;
  445. }
  446. #ifdef DEBUG
  447. printf("get_default_args(%s,%d)\n", str, num);
  448. #endif
  449. return 0;
  450. }
  451. static void
  452. print_help(void)
  453. {
  454. printf("Commands:\n"
  455. " h, ? Display this message\n"
  456. " q Halt the system and return to SRM\n"
  457. " p 1-8 Look in partition <num> for configuration/kernel\n"
  458. " l List preconfigured kernels\n"
  459. " d <dir> List directory <dir> in current filesystem\n"
  460. " b <file> <args> Boot kernel in <file> (- for raw boot)\n"
  461. " i <file> Use <file> as initial ramdisk\n"
  462. " with arguments <args>\n"
  463. " 0-9 Boot preconfiguration 0-9 (list with 'l')\n");
  464. }
  465. static void
  466. get_aboot_options (long dev)
  467. {
  468. int preset = 0; /* no preset */
  469. int interactive = 0; /* non-interactive */
  470. char *extra_args = NULL;
  471. #ifdef DEBUG
  472. printf("get_aboot_options(%lx)\n",dev);
  473. printf("kernel_args=\"%s\"\n",kernel_args);
  474. #endif
  475. /* Forms of -flags argument from SRM */
  476. if (kernel_args[0] >= '1' && kernel_args[0] <= '9'
  477. && kernel_args[1] == ':' && kernel_args[2]
  478. && (kernel_args[3] == '\0' || kernel_args[3] == ' '))
  479. {
  480. /* <partition>:<preset> - where <preset> is an entry
  481. in /etc/aboot.conf (to be found on <partition>), or
  482. 'i' for interactive */
  483. config_file_partition = kernel_args[0] - '0';
  484. preset = kernel_args[2];
  485. if (kernel_args[3]) {
  486. extra_args=&kernel_args[3];
  487. while (*extra_args == ' ') { extra_args++; }
  488. if (*extra_args == '\0') extra_args = NULL;
  489. }
  490. #ifdef DEBUG
  491. printf("partition:preset = %ld:%c\n", config_file_partition,
  492. preset);
  493. #endif
  494. } else if (kernel_args[0]
  495. && (kernel_args[1] == '\0' || kernel_args[1] == ' ')) {
  496. /* Single character option, for Jensen and friends -
  497. this is either a preconfigured entry in
  498. /etc/aboot.conf or 'i' for interactive*/
  499. if (kernel_args[0] == 'i') interactive = 1;
  500. else {
  501. preset = kernel_args[0];
  502. if (kernel_args[1]) {
  503. /* are there actually extra args? */
  504. extra_args=&kernel_args[1];
  505. while (*extra_args == ' ') { extra_args++; }
  506. if (*extra_args == '\0') extra_args = NULL;
  507. }
  508. }
  509. } else if (kernel_args[0] == '\0') {
  510. interactive = 1;
  511. } else {
  512. /* attempt to parse the arguments given */
  513. }
  514. #ifdef DEBUG
  515. if (extra_args) printf("extra args: \"%s\"\n",extra_args);
  516. #endif
  517. if (preset || interactive) {
  518. char buf[256], *p;
  519. struct bootfs *fs = 0;
  520. static int first = 1;
  521. int done = 0;
  522. while (!done) {
  523. /* If we have a setting from /etc/aboot.conf, use it */
  524. if (preset) {
  525. #ifdef DEBUG
  526. printf("trying preset %c\n", preset);
  527. #endif
  528. if (!fs) {
  529. fs = mount_fs(dev, config_file_partition);
  530. if (!fs) {
  531. preset = 0;
  532. continue;
  533. }
  534. }
  535. if (get_default_args(fs, buf, preset) >= 0)
  536. break;
  537. /* Doh, keep on going */
  538. preset = 0;
  539. continue;
  540. }
  541. /* Otherwise, clear out kernel_args and prompt the user */
  542. kernel_args[0] = 0;
  543. if (first) {
  544. printf("Welcome to aboot " ABOOT_VERSION "\n");
  545. print_help();
  546. first = 0;
  547. }
  548. printf("aboot> ");
  549. #ifdef TESTING
  550. fgets(buf, sizeof(buf), stdin);
  551. buf[strlen(buf)-1] = 0;
  552. #else
  553. getline(buf, sizeof(buf));
  554. #endif
  555. printf("\n");
  556. switch (buf[0]) {
  557. case 'h':
  558. case '?':
  559. print_help();
  560. break;
  561. case 'q':
  562. halt();
  563. break;
  564. case 'p':
  565. p = strchr(buf, ' ');
  566. while (p && *p == ' ') ++p;
  567. if (p && p[0] >= '1' && p[0] <= '8'
  568. && (p[1] == '\0' || p[1] == ' ')) {
  569. config_file_partition = p[0] - '0';
  570. fs = 0; /* force reread */
  571. } else {
  572. printf("Please specify a number between 1 and 8\n");
  573. }
  574. break;
  575. case 'l':
  576. if (!fs) {
  577. fs = mount_fs(dev, config_file_partition);
  578. if (!fs) {
  579. printf("Partition %ld is invalid. "
  580. "Please specify another with 'p'\n",
  581. config_file_partition);
  582. continue;
  583. }
  584. }
  585. print_config_file(fs);
  586. break;
  587. case 'd':
  588. if (!fs) {
  589. fs = mount_fs(dev, config_file_partition);
  590. if (!fs) {
  591. printf("Partition %ld is invalid. "
  592. "Please specify another with 'p'\n",
  593. config_file_partition);
  594. continue;
  595. }
  596. }
  597. /* skip past whitespace */
  598. p = strchr(buf, ' ');
  599. while (p && *p == ' ') ++p;
  600. if (p)
  601. list_directory(fs, p);
  602. else
  603. list_directory(fs, "/");
  604. break;
  605. case 'b':
  606. /* skip past whitespace */
  607. p = strchr(buf, ' ');
  608. while (p && *p == ' ') ++p;
  609. if (p) {
  610. strcpy(buf, p);
  611. done = 1;
  612. } else {
  613. printf("Please specify a file to load the kernel from, "
  614. "or '-' to load the kernel from the boot sector\n");
  615. }
  616. break;
  617. case 'i':
  618. /* skip past whitespace */
  619. p = strchr(buf, ' ');
  620. while (p && *p == ' ') ++p;
  621. if (p)
  622. strcpy(initrd_file, p);
  623. else {
  624. printf("Please specify a file to use as initial ramdisk\n");
  625. }
  626. break;
  627. case '0' ... '9':
  628. preset = buf[0];
  629. p = strchr(buf, ' ');
  630. while (p && *p == ' ') ++p;
  631. if (p) {
  632. strcpy(kernel_args, p);
  633. extra_args=kernel_args;
  634. }
  635. break;
  636. default:
  637. break;
  638. }
  639. }
  640. /* if we have extra args, append them to buf */
  641. if (extra_args) {
  642. p=buf; while (p && *p) p++;
  643. *p++=' ';
  644. strcpy(p, extra_args);
  645. }
  646. /* split on space into kernel + args */
  647. p = strchr(buf, ' ');
  648. if (p) {
  649. /* skip past leading whitespace */
  650. *p++ = '\0';
  651. while (p && *p == ' ') ++p;
  652. strcpy(kernel_args, p);
  653. }
  654. strcpy(boot_file, buf);
  655. }
  656. #ifdef DEBUG
  657. printf("boot_file=\"%s\", kernel_args=\"%s\"\n",boot_file,kernel_args);
  658. #endif
  659. {
  660. /* parse off initrd= option from kernel_args if any */
  661. char *p = kernel_args;
  662. /* poor man's strstr */
  663. do {
  664. if (strncmp(p, "initrd=", 7) == 0)
  665. break;
  666. } while (*p++);
  667. if (*p) {
  668. char *a = p + 7; /* argument */
  669. char *e = strchr (a, ' ');
  670. if (e) {
  671. strncpy(initrd_file, a, e-a);
  672. initrd_file[e-a] = 0;
  673. strcpy(p, e);
  674. } else {
  675. strcpy(initrd_file, a);
  676. *p = 0;
  677. }
  678. }
  679. }
  680. /* parse off partition number from boot_file if any: */
  681. if (boot_file[0] >= '0' && boot_file[0] <= '9' && boot_file[1] == '/')
  682. {
  683. boot_part = boot_file[0] - '0';
  684. strcpy(boot_file, boot_file + 2);
  685. } else {
  686. boot_part = config_file_partition;
  687. }
  688. }
  689. static long
  690. load (long dev)
  691. {
  692. char *fname;
  693. #ifdef DEBUG
  694. printf("load(%lx)\n", dev);
  695. #endif
  696. fname = boot_file;
  697. if (fname[0] == '-' && fname[1] == '\0') {
  698. /* a single "-" implies raw boot: */
  699. if (load_raw(dev) < 0) {
  700. return -1;
  701. }
  702. } else {
  703. /* if there's no disklabel, boot_part will be ignored anyway */
  704. bfs = mount_fs(dev, boot_part);
  705. if (!bfs) {
  706. printf("aboot: mount of partition %d failed\n", boot_part);
  707. return -1;
  708. }
  709. if (read_kernel(fname) < 0) {
  710. return -1;
  711. }
  712. }
  713. /* clear bss: */
  714. printf("aboot: zero-filling %ld bytes at 0x%p\n", bss_size, bss_start);
  715. #ifndef TESTING
  716. memset((char*)bss_start, 0, bss_size);
  717. #endif
  718. if (initrd_file[0] == 0)
  719. return 0;
  720. /* work around a bug in the ext2 code */
  721. bfs = mount_fs(dev, boot_part);
  722. if (!bfs) {
  723. printf("aboot: mount of partition %d failed\n", boot_part);
  724. return -1;
  725. }
  726. if (read_initrd() < 0) {
  727. return -1;
  728. }
  729. return 0;
  730. }
  731. long
  732. load_kernel (void)
  733. {
  734. char envval[256];
  735. long result;
  736. long dev;
  737. #ifdef TESTING
  738. const char *e;
  739. if ((e = getenv("BOOTED_DEV"))) {
  740. strncpy(envval, e, sizeof(envval)-1);
  741. envval[sizeof(envval)-1] = 0;
  742. } else {
  743. printf("aboot: Can't get BOOTED_DEV environment variable!\n");
  744. return -1;
  745. }
  746. #else
  747. if (cons_getenv(ENV_BOOTED_DEV, envval, sizeof(envval)) < 0) {
  748. printf("aboot: Can't get BOOTED_DEV environment variable!\n");
  749. return -1;
  750. }
  751. #endif
  752. printf("aboot: booting from device '%s'\n", envval);
  753. dev = cons_open(envval);
  754. if (dev < 0) {
  755. printf("aboot: unable to open boot device `%s': %lx\n",
  756. envval, dev);
  757. return -1;
  758. }
  759. dev &= 0xffffffff;
  760. get_disklabel(dev);
  761. while (1) {
  762. get_aboot_options(dev);
  763. result = load(dev);
  764. if (result != -1)
  765. break;
  766. /* load failed---query user interactively */
  767. strcpy(kernel_args, "i");
  768. }
  769. #ifdef DEBUG
  770. printf("load done\n");
  771. #endif
  772. cons_close(dev);
  773. return result;
  774. }