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