cmd_disk.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * (C) Copyright 2000-2011
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. *
  23. */
  24. #include <common.h>
  25. #include <command.h>
  26. int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
  27. char *const argv[])
  28. {
  29. char *boot_device = NULL;
  30. char *ep;
  31. int dev, part = 0;
  32. ulong addr, cnt;
  33. disk_partition_t info;
  34. image_header_t *hdr;
  35. block_dev_desc_t *dev_desc;
  36. #if defined(CONFIG_FIT)
  37. const void *fit_hdr = NULL;
  38. #endif
  39. bootstage_mark(BOOTSTAGE_ID_IDE_START);
  40. switch (argc) {
  41. case 1:
  42. addr = CONFIG_SYS_LOAD_ADDR;
  43. boot_device = getenv("bootdevice");
  44. break;
  45. case 2:
  46. addr = simple_strtoul(argv[1], NULL, 16);
  47. boot_device = getenv("bootdevice");
  48. break;
  49. case 3:
  50. addr = simple_strtoul(argv[1], NULL, 16);
  51. boot_device = argv[2];
  52. break;
  53. default:
  54. bootstage_error(BOOTSTAGE_ID_IDE_ADDR);
  55. return CMD_RET_USAGE;
  56. }
  57. bootstage_mark(BOOTSTAGE_ID_IDE_ADDR);
  58. if (!boot_device) {
  59. puts("\n** No boot device **\n");
  60. bootstage_error(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
  61. return 1;
  62. }
  63. bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
  64. dev = simple_strtoul(boot_device, &ep, 16);
  65. dev_desc = get_dev(intf, dev);
  66. if (dev_desc->type == DEV_TYPE_UNKNOWN) {
  67. printf("\n** Device %d not available\n", dev);
  68. bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
  69. return 1;
  70. }
  71. bootstage_mark(BOOTSTAGE_ID_IDE_TYPE);
  72. if (*ep) {
  73. if (*ep != ':') {
  74. puts("\n** Invalid boot device, use `dev[:part]' **\n");
  75. bootstage_error(BOOTSTAGE_ID_IDE_PART);
  76. return 1;
  77. }
  78. part = simple_strtoul(++ep, NULL, 16);
  79. }
  80. bootstage_mark(BOOTSTAGE_ID_IDE_PART);
  81. if (get_partition_info(dev_desc, part, &info)) {
  82. bootstage_error(BOOTSTAGE_ID_IDE_PART_INFO);
  83. return 1;
  84. }
  85. bootstage_mark(BOOTSTAGE_ID_IDE_PART_INFO);
  86. if ((strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0)
  87. &&
  88. (strncmp((char *)info.type, BOOT_PART_COMP, sizeof(info.type)) != 0)
  89. ) {
  90. printf("\n** Invalid partition type \"%.32s\"" " (expect \""
  91. BOOT_PART_TYPE "\")\n",
  92. info.type);
  93. bootstage_error(BOOTSTAGE_ID_IDE_PART_TYPE);
  94. return 1;
  95. }
  96. bootstage_mark(BOOTSTAGE_ID_IDE_PART_TYPE);
  97. printf("\nLoading from disk device %d, partition %d: "
  98. "Name: %.32s Type: %.32s\n", dev, part, info.name, info.type);
  99. debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n",
  100. info.start, info.size, info.blksz);
  101. if (dev_desc->block_read(dev, info.start, 1, (ulong *) addr) != 1) {
  102. printf("** Read error on %d:%d\n", dev, part);
  103. bootstage_error(BOOTSTAGE_ID_IDE_PART_READ);
  104. return 1;
  105. }
  106. bootstage_mark(BOOTSTAGE_ID_IDE_PART_READ);
  107. switch (genimg_get_format((void *) addr)) {
  108. case IMAGE_FORMAT_LEGACY:
  109. hdr = (image_header_t *) addr;
  110. bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT);
  111. if (!image_check_hcrc(hdr)) {
  112. puts("\n** Bad Header Checksum **\n");
  113. bootstage_error(BOOTSTAGE_ID_IDE_CHECKSUM);
  114. return 1;
  115. }
  116. bootstage_mark(BOOTSTAGE_ID_IDE_CHECKSUM);
  117. image_print_contents(hdr);
  118. cnt = image_get_image_size(hdr);
  119. break;
  120. #if defined(CONFIG_FIT)
  121. case IMAGE_FORMAT_FIT:
  122. fit_hdr = (const void *) addr;
  123. puts("Fit image detected...\n");
  124. cnt = fit_get_size(fit_hdr);
  125. break;
  126. #endif
  127. default:
  128. bootstage_error(BOOTSTAGE_ID_IDE_FORMAT);
  129. puts("** Unknown image type\n");
  130. return 1;
  131. }
  132. cnt += info.blksz - 1;
  133. cnt /= info.blksz;
  134. cnt -= 1;
  135. if (dev_desc->block_read(dev, info.start + 1, cnt,
  136. (ulong *)(addr + info.blksz)) != cnt) {
  137. printf("** Read error on %d:%d\n", dev, part);
  138. bootstage_error(BOOTSTAGE_ID_IDE_READ);
  139. return 1;
  140. }
  141. bootstage_mark(BOOTSTAGE_ID_IDE_READ);
  142. #if defined(CONFIG_FIT)
  143. /* This cannot be done earlier,
  144. * we need complete FIT image in RAM first */
  145. if (genimg_get_format((void *) addr) == IMAGE_FORMAT_FIT) {
  146. if (!fit_check_format(fit_hdr)) {
  147. bootstage_error(BOOTSTAGE_ID_IDE_FIT_READ);
  148. puts("** Bad FIT image format\n");
  149. return 1;
  150. }
  151. bootstage_mark(BOOTSTAGE_ID_IDE_FIT_READ_OK);
  152. fit_print_contents(fit_hdr);
  153. }
  154. #endif
  155. flush_cache(addr, (cnt+1)*info.blksz);
  156. /* Loading ok, update default load address */
  157. load_addr = addr;
  158. return bootm_maybe_autostart(cmdtp, argv[0]);
  159. }