cmd_zfs.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. *
  3. * ZFS filesystem porting to Uboot by
  4. * Jorgen Lundman <lundman at lundman.net>
  5. *
  6. * zfsfs support
  7. * made from existing GRUB Sources by Sun, GNU and others.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. *
  24. */
  25. #include <common.h>
  26. #include <part.h>
  27. #include <config.h>
  28. #include <command.h>
  29. #include <image.h>
  30. #include <linux/ctype.h>
  31. #include <asm/byteorder.h>
  32. #include <zfs_common.h>
  33. #include <linux/stat.h>
  34. #include <malloc.h>
  35. #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
  36. #include <usb.h>
  37. #endif
  38. #if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION)
  39. #error DOS or EFI partition support must be selected
  40. #endif
  41. #define DOS_PART_MAGIC_OFFSET 0x1fe
  42. #define DOS_FS_TYPE_OFFSET 0x36
  43. #define DOS_FS32_TYPE_OFFSET 0x52
  44. static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  45. {
  46. char *filename = NULL;
  47. char *ep;
  48. int dev;
  49. unsigned long part = 1;
  50. ulong addr = 0;
  51. ulong part_length;
  52. disk_partition_t info;
  53. char buf[12];
  54. unsigned long count;
  55. const char *addr_str;
  56. struct zfs_file zfile;
  57. struct device_s vdev;
  58. if (argc < 3)
  59. return CMD_RET_USAGE;
  60. count = 0;
  61. addr = simple_strtoul(argv[3], NULL, 16);
  62. filename = getenv("bootfile");
  63. switch (argc) {
  64. case 3:
  65. addr_str = getenv("loadaddr");
  66. if (addr_str != NULL)
  67. addr = simple_strtoul(addr_str, NULL, 16);
  68. else
  69. addr = CONFIG_SYS_LOAD_ADDR;
  70. break;
  71. case 4:
  72. break;
  73. case 5:
  74. filename = argv[4];
  75. break;
  76. case 6:
  77. filename = argv[4];
  78. count = simple_strtoul(argv[5], NULL, 16);
  79. break;
  80. default:
  81. return cmd_usage(cmdtp);
  82. }
  83. if (!filename) {
  84. puts("** No boot file defined **\n");
  85. return 1;
  86. }
  87. dev = (int)simple_strtoul(argv[2], &ep, 16);
  88. zfs_dev_desc = get_dev(argv[1], dev);
  89. if (zfs_dev_desc == NULL) {
  90. printf("** Block device %s %d not supported\n", argv[1], dev);
  91. return 1;
  92. }
  93. if (*ep) {
  94. if (*ep != ':') {
  95. puts("** Invalid boot device, use `dev[:part]' **\n");
  96. return 1;
  97. }
  98. part = simple_strtoul(++ep, NULL, 16);
  99. }
  100. if (part != 0) {
  101. if (get_partition_info(zfs_dev_desc, part, &info)) {
  102. printf("** Bad partition %lu **\n", part);
  103. return 1;
  104. }
  105. if (strncmp((char *)info.type, BOOT_PART_TYPE,
  106. strlen(BOOT_PART_TYPE)) != 0) {
  107. printf("** Invalid partition type \"%s\" (expect \"" BOOT_PART_TYPE "\")\n",
  108. info.type);
  109. return 1;
  110. }
  111. printf("Loading file \"%s\" "
  112. "from %s device %d:%lu %s\n",
  113. filename, argv[1], dev, part, info.name);
  114. } else {
  115. printf("Loading file \"%s\" from %s device %d\n",
  116. filename, argv[1], dev);
  117. }
  118. part_length = zfs_set_blk_dev(zfs_dev_desc, part);
  119. if (part_length == 0) {
  120. printf("**Bad partition - %s %d:%lu **\n", argv[1], dev, part);
  121. return 1;
  122. }
  123. vdev.part_length = part_length;
  124. memset(&zfile, 0, sizeof(zfile));
  125. zfile.device = &vdev;
  126. if (zfs_open(&zfile, filename)) {
  127. printf("** File not found %s\n", filename);
  128. return 1;
  129. }
  130. if ((count < zfile.size) && (count != 0))
  131. zfile.size = (uint64_t)count;
  132. if (zfs_read(&zfile, (char *)addr, zfile.size) != zfile.size) {
  133. printf("** Unable to read \"%s\" from %s %d:%lu **\n",
  134. filename, argv[1], dev, part);
  135. zfs_close(&zfile);
  136. return 1;
  137. }
  138. zfs_close(&zfile);
  139. /* Loading ok, update default load address */
  140. load_addr = addr;
  141. printf("%llu bytes read\n", zfile.size);
  142. sprintf(buf, "%llX", zfile.size);
  143. setenv("filesize", buf);
  144. return 0;
  145. }
  146. int zfs_print(const char *entry, const struct zfs_dirhook_info *data)
  147. {
  148. printf("%s %s\n",
  149. data->dir ? "<DIR> " : " ",
  150. entry);
  151. return 0; /* 0 continue, 1 stop */
  152. }
  153. static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  154. {
  155. const char *filename = "/";
  156. int dev;
  157. unsigned long part = 1;
  158. char *ep;
  159. int part_length;
  160. struct device_s vdev;
  161. if (argc < 3)
  162. return cmd_usage(cmdtp);
  163. dev = (int)simple_strtoul(argv[2], &ep, 16);
  164. zfs_dev_desc = get_dev(argv[1], dev);
  165. if (zfs_dev_desc == NULL) {
  166. printf("\n** Block device %s %d not supported\n", argv[1], dev);
  167. return 1;
  168. }
  169. if (*ep) {
  170. if (*ep != ':') {
  171. puts("\n** Invalid boot device, use `dev[:part]' **\n");
  172. return 1;
  173. }
  174. part = simple_strtoul(++ep, NULL, 16);
  175. }
  176. if (argc == 4)
  177. filename = argv[3];
  178. part_length = zfs_set_blk_dev(zfs_dev_desc, part);
  179. if (part_length == 0) {
  180. printf("** Bad partition - %s %d:%lu **\n", argv[1], dev, part);
  181. return 1;
  182. }
  183. vdev.part_length = part_length;
  184. zfs_ls(&vdev, filename,
  185. zfs_print);
  186. return 0;
  187. }
  188. U_BOOT_CMD(zfsls, 4, 1, do_zfs_ls,
  189. "list files in a directory (default /)",
  190. "<interface> <dev[:part]> [directory]\n"
  191. " - list files from 'dev' on 'interface' in a '/DATASET/@/$dir/'");
  192. U_BOOT_CMD(zfsload, 6, 0, do_zfs_load,
  193. "load binary file from a ZFS filesystem",
  194. "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
  195. " - load binary file '/DATASET/@/$dir/$file' from 'dev' on 'interface'\n"
  196. " to address 'addr' from ZFS filesystem");