Home | History | Annotate | Download | only in cmd
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  *
      4  * ZFS filesystem porting to Uboot by
      5  * Jorgen Lundman <lundman at lundman.net>
      6  *
      7  * zfsfs support
      8  * made from existing GRUB Sources by Sun, GNU and others.
      9  */
     10 
     11 #include <common.h>
     12 #include <part.h>
     13 #include <config.h>
     14 #include <command.h>
     15 #include <image.h>
     16 #include <linux/ctype.h>
     17 #include <asm/byteorder.h>
     18 #include <zfs_common.h>
     19 #include <linux/stat.h>
     20 #include <malloc.h>
     21 
     22 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
     23 #include <usb.h>
     24 #endif
     25 
     26 #if !CONFIG_IS_ENABLED(DOS_PARTITION) && !CONFIG_IS_ENABLED(EFI_PARTITION)
     27 #error DOS or EFI partition support must be selected
     28 #endif
     29 
     30 #define DOS_PART_MAGIC_OFFSET	0x1fe
     31 #define DOS_FS_TYPE_OFFSET	0x36
     32 #define DOS_FS32_TYPE_OFFSET	0x52
     33 
     34 static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
     35 {
     36 	char *filename = NULL;
     37 	int dev;
     38 	int part;
     39 	ulong addr = 0;
     40 	disk_partition_t info;
     41 	struct blk_desc *dev_desc;
     42 	char buf[12];
     43 	unsigned long count;
     44 	const char *addr_str;
     45 	struct zfs_file zfile;
     46 	struct device_s vdev;
     47 
     48 	if (argc < 3)
     49 		return CMD_RET_USAGE;
     50 
     51 	count = 0;
     52 	addr = simple_strtoul(argv[3], NULL, 16);
     53 	filename = env_get("bootfile");
     54 	switch (argc) {
     55 	case 3:
     56 		addr_str = env_get("loadaddr");
     57 		if (addr_str != NULL)
     58 			addr = simple_strtoul(addr_str, NULL, 16);
     59 		else
     60 			addr = CONFIG_SYS_LOAD_ADDR;
     61 
     62 		break;
     63 	case 4:
     64 		break;
     65 	case 5:
     66 		filename = argv[4];
     67 		break;
     68 	case 6:
     69 		filename = argv[4];
     70 		count = simple_strtoul(argv[5], NULL, 16);
     71 		break;
     72 
     73 	default:
     74 		return cmd_usage(cmdtp);
     75 	}
     76 
     77 	if (!filename) {
     78 		puts("** No boot file defined **\n");
     79 		return 1;
     80 	}
     81 
     82 	part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
     83 	if (part < 0)
     84 		return 1;
     85 
     86 	dev = dev_desc->devnum;
     87 	printf("Loading file \"%s\" from %s device %d%c%c\n",
     88 		filename, argv[1], dev,
     89 		part ? ':' : ' ', part ? part + '0' : ' ');
     90 
     91 	zfs_set_blk_dev(dev_desc, &info);
     92 	vdev.part_length = info.size;
     93 
     94 	memset(&zfile, 0, sizeof(zfile));
     95 	zfile.device = &vdev;
     96 	if (zfs_open(&zfile, filename)) {
     97 		printf("** File not found %s **\n", filename);
     98 		return 1;
     99 	}
    100 
    101 	if ((count < zfile.size) && (count != 0))
    102 		zfile.size = (uint64_t)count;
    103 
    104 	if (zfs_read(&zfile, (char *)addr, zfile.size) != zfile.size) {
    105 		printf("** Unable to read \"%s\" from %s %d:%d **\n",
    106 			   filename, argv[1], dev, part);
    107 		zfs_close(&zfile);
    108 		return 1;
    109 	}
    110 
    111 	zfs_close(&zfile);
    112 
    113 	/* Loading ok, update default load address */
    114 	load_addr = addr;
    115 
    116 	printf("%llu bytes read\n", zfile.size);
    117 	env_set_hex("filesize", zfile.size);
    118 
    119 	return 0;
    120 }
    121 
    122 
    123 int zfs_print(const char *entry, const struct zfs_dirhook_info *data)
    124 {
    125 	printf("%s %s\n",
    126 		   data->dir ? "<DIR> " : "		 ",
    127 		   entry);
    128 	return 0; /* 0 continue, 1 stop */
    129 }
    130 
    131 
    132 
    133 static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    134 {
    135 	const char *filename = "/";
    136 	int part;
    137 	struct blk_desc *dev_desc;
    138 	disk_partition_t info;
    139 	struct device_s vdev;
    140 
    141 	if (argc < 2)
    142 		return cmd_usage(cmdtp);
    143 
    144 	if (argc == 4)
    145 		filename = argv[3];
    146 
    147 	part = blk_get_device_part_str(argv[1], argv[2], &dev_desc, &info, 1);
    148 	if (part < 0)
    149 		return 1;
    150 
    151 	zfs_set_blk_dev(dev_desc, &info);
    152 	vdev.part_length = info.size;
    153 
    154 	zfs_ls(&vdev, filename,
    155 		   zfs_print);
    156 
    157 	return 0;
    158 }
    159 
    160 
    161 U_BOOT_CMD(zfsls, 4, 1, do_zfs_ls,
    162 		   "list files in a directory (default /)",
    163 		   "<interface> <dev[:part]> [directory]\n"
    164 		   "	  - list files from 'dev' on 'interface' in a '/DATASET/@/$dir/'");
    165 
    166 U_BOOT_CMD(zfsload, 6, 0, do_zfs_load,
    167 		   "load binary file from a ZFS filesystem",
    168 		   "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
    169 		   "	  - load binary file '/DATASET/@/$dir/$file' from 'dev' on 'interface'\n"
    170 		   "		 to address 'addr' from ZFS filesystem");
    171