[U-Boot] [PATCH 10/11] DM: use new blockdev API in ZFS

Pavel Herrmann morpheus.ibis at gmail.com
Thu Sep 20 21:37:46 CEST 2012


cmd_zfsdm.c is a copy of cmd_zfs.c with just trivial changes, but those touch
large portion of the lines due to different number of parameters (old API has a
separate parameter for interface and for disk number, new API has this as one)

Signed-off-by: Pavel Herrmann <morpheus.ibis at gmail.com>
---
 common/Makefile      |   3 +
 common/cmd_zfsdm.c   | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/zfs/Makefile      |   7 +-
 fs/zfs/dev_dm.c      | 117 ++++++++++++++++++++++++++++++
 include/zfs_common.h |   8 +++
 5 files changed, 333 insertions(+), 1 deletion(-)
 create mode 100644 common/cmd_zfsdm.c
 create mode 100644 fs/zfs/dev_dm.c

diff --git a/common/Makefile b/common/Makefile
index d83c66e..11bf888 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -172,6 +172,9 @@ endif
 COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o
 COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o
 COBJS-$(CONFIG_CMD_SPL) += cmd_spl.o
+ifdef CONFIG_DM
+COBJS-$(CONFIG_CMD_ZFS) += cmd_zfsdm.o
+else
 COBJS-$(CONFIG_CMD_ZFS) += cmd_zfs.o
 endif
 
diff --git a/common/cmd_zfsdm.c b/common/cmd_zfsdm.c
new file mode 100644
index 0000000..e41f956
--- /dev/null
+++ b/common/cmd_zfsdm.c
@@ -0,0 +1,199 @@
+/*
+ *
+ * ZFS filesystem porting to Uboot by
+ * Jorgen Lundman <lundman at lundman.net>
+ *
+ * zfsfs support
+ * made from existing GRUB Sources by Sun, GNU and others.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <part.h>
+#include <config.h>
+#include <command.h>
+#include <image.h>
+#include <linux/ctype.h>
+#include <asm/byteorder.h>
+#include <zfs_common.h>
+#include <linux/stat.h>
+#include <malloc.h>
+#include <dm/structures.h>
+#include <dm/blockdev.h>
+
+#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
+#include <usb.h>
+#endif
+
+#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION)
+#error DOS or EFI partition support must be selected
+#endif
+
+#define DOS_PART_MAGIC_OFFSET	0x1fe
+#define DOS_FS_TYPE_OFFSET	0x36
+#define DOS_FS32_TYPE_OFFSET	0x52
+
+static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc,
+	char * const argv[])
+{
+	char *filename = NULL;
+	ulong addr = 0;
+	ulong part_length;
+	char buf[12];
+	unsigned long count;
+	const char *addr_str;
+	struct zfs_file zfile;
+	struct device_s vdev;
+	struct instance *bdev;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	count = 0;
+	switch (argc) {
+	case 2:
+		addr_str = getenv("loadaddr");
+		if (addr_str != NULL)
+			addr = simple_strtoul(addr_str, NULL, 16);
+		else
+			addr = CONFIG_SYS_LOAD_ADDR;
+
+		break;
+	case 3:
+		addr = simple_strtoul(argv[2], NULL, 16);
+		filename = getenv("bootfile");
+		break;
+	case 4:
+		addr = simple_strtoul(argv[2], NULL, 16);
+		filename = argv[3];
+		break;
+	case 5:
+		addr = simple_strtoul(argv[2], NULL, 16);
+		filename = argv[3];
+		count = simple_strtoul(argv[4], NULL, 16);
+		break;
+
+	default:
+		return cmd_usage(cmdtp);
+	}
+
+	if (!filename) {
+		puts("** No boot file defined **\n");
+		return 1;
+	}
+
+	bdev = get_blockdev_by_name(argv[1]);
+	if (!bdev) {
+		printf("** Block device %s not supported\n", argv[1]);
+		return 1;
+	}
+
+	printf("Loading file \"%s\" from device %s\n",
+		   filename, argv[1]);
+
+	part_length = zfs_set_blk_dev(bdev);
+	if (part_length == 0) {
+		printf("**Bad partition - %s **\n", argv[1]);
+		return 1;
+	}
+
+	vdev.part_length = part_length;
+
+	memset(&zfile, 0, sizeof(zfile));
+	zfile.device = &vdev;
+	if (zfs_open(&zfile, filename)) {
+		printf("** File not found %s\n", filename);
+		return 1;
+	}
+
+	if ((count < zfile.size) && (count != 0))
+		zfile.size = (uint64_t)count;
+
+	if (zfs_read(&zfile, (char *)addr, zfile.size) != zfile.size) {
+		printf("** Unable to read \"%s\" from %s **\n",
+			   filename, argv[1]);
+		zfs_close(&zfile);
+		return 1;
+	}
+
+	zfs_close(&zfile);
+
+	/* Loading ok, update default load address */
+	load_addr = addr;
+
+	printf("%llu bytes read\n", zfile.size);
+	sprintf(buf, "%llX", zfile.size);
+	setenv("filesize", buf);
+
+	return 0;
+}
+
+
+int zfs_print(const char *entry, const struct zfs_dirhook_info *data)
+{
+	printf("%s %s\n",
+		   data->dir ? "<DIR> " : "		 ",
+		   entry);
+	return 0; /* 0 continue, 1 stop */
+}
+
+
+
+static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const char *filename = "/";
+	int part_length;
+	struct device_s vdev;
+	struct instance *bdev;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	bdev = get_blockdev_by_name(argv[1]);
+	if (bdev) {
+		printf("\n** Block device %s not supported\n", argv[1]);
+		return 1;
+	}
+	if (argc == 3)
+		filename = argv[2];
+
+	part_length = zfs_set_blk_dev(bdev);
+	if (part_length == 0) {
+		printf("** Bad partition - %s **\n", argv[1]);
+		return 1;
+	}
+
+	vdev.part_length = part_length;
+
+	zfs_ls(&vdev, filename,
+		   zfs_print);
+
+	return 0;
+}
+
+
+U_BOOT_CMD(zfsls, 3, 1, do_zfs_ls,
+		   "list files in a directory (default /)",
+		   "<dev[:part]> [directory]\n"
+		   "	  - list files from 'dev' in a '/DATASET/@/$dir/'");
+
+U_BOOT_CMD(zfsload, 5, 0, do_zfs_load,
+		   "load binary file from a ZFS filesystem",
+		   "<dev[:part]> [addr] [filename] [bytes]\n"
+		   "	  - load binary file '/DATASET/@/$dir/$file' from 'dev'\n"
+		   "		 to address 'addr' from ZFS filesystem");
diff --git a/fs/zfs/Makefile b/fs/zfs/Makefile
index 938fc5e..4765a56 100644
--- a/fs/zfs/Makefile
+++ b/fs/zfs/Makefile
@@ -26,7 +26,12 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libzfs.o
 
 AOBJS	=
-COBJS-$(CONFIG_CMD_ZFS) := dev.o zfs.o zfs_fletcher.o zfs_sha256.o zfs_lzjb.o
+COBJS-$(CONFIG_CMD_ZFS) := zfs.o zfs_fletcher.o zfs_sha256.o zfs_lzjb.o
+ifdef CONFIG_DM
+COBJS-$(CONFIG_CMD_ZFS) := deo_dm.o
+else
+COBJS-$(CONFIG_CMD_ZFS) := dev.o
+endif
 
 SRCS	:= $(AOBJS:.o=.S) $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(AOBJS) $(COBJS-y))
diff --git a/fs/zfs/dev_dm.c b/fs/zfs/dev_dm.c
new file mode 100644
index 0000000..8af0546
--- /dev/null
+++ b/fs/zfs/dev_dm.c
@@ -0,0 +1,117 @@
+/*
+ *
+ *	based on code of fs/reiserfs/dev.c by
+ *
+ *	(C) Copyright 2003 - 2004
+ *	Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba at sysgo.com>
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <common.h>
+#include <config.h>
+#include <zfs_common.h>
+#include <dm/structures.h>
+#include <dm/blockdev.h>
+
+static struct instance *bdev;
+
+int zfs_set_blk_dev(struct instance *dev)
+{
+	int error;
+	struct option op;
+
+	if (!dev)
+		return 0;
+
+	error = blockdev_get_option(dev, BLKD_OPT_BLOCKCOUNT, &op);
+	if (error || (OPTION_TYPE(op) != OPTION_TYPE_U))
+		return 0;
+
+	bdev = dev;
+
+	return op.data.data_u;
+}
+
+/* err */
+int zfs_devread(int sector, int byte_offset, int byte_len, char *buf)
+{
+	short sec_buffer[SECTOR_SIZE/sizeof(short)];
+	char *sec_buf = (char *)sec_buffer;
+	unsigned block_len;
+
+	/*
+	 *	Get the read to the beginning of a partition.
+	 */
+	sector += byte_offset >> SECTOR_BITS;
+	byte_offset &= SECTOR_SIZE - 1;
+
+	debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len);
+
+	if (!bdev) {
+		printf("** Invalid Block Device Descriptor (NULL)\n");
+		return 1;
+	}
+
+	if (byte_offset != 0) {
+		/* read first part which isn't aligned with start of sector */
+		if (blockdev_read(bdev, sector, 1, sec_buf) != 1) {
+			printf(" ** zfs_devread() read error **\n");
+			return 1;
+		}
+		memcpy(buf, sec_buf + byte_offset,
+			   min(SECTOR_SIZE - byte_offset, byte_len));
+		buf += min(SECTOR_SIZE - byte_offset, byte_len);
+		byte_len -= min(SECTOR_SIZE - byte_offset, byte_len);
+		sector++;
+	}
+
+	if (byte_len == 0)
+		return 0;
+
+	/*	read sector aligned part */
+	block_len = byte_len & ~(SECTOR_SIZE - 1);
+
+	if (block_len == 0) {
+		u8 p[SECTOR_SIZE];
+
+		block_len = SECTOR_SIZE;
+		blockdev_read(bdev, sector, 1, p);
+		memcpy(buf, p, byte_len);
+		return 0;
+	}
+
+	if (blockdev_read(bdev, sector, block_len / SECTOR_SIZE, buf) !=
+	    block_len / SECTOR_SIZE) {
+		printf(" ** zfs_devread() read error - block\n");
+		return 1;
+	}
+
+	block_len = byte_len & ~(SECTOR_SIZE - 1);
+	buf += block_len;
+	byte_len -= block_len;
+	sector += block_len / SECTOR_SIZE;
+
+	if (byte_len != 0) {
+		/* read rest of data which are not in whole sector */
+		if (blockdev_read(bdev, sector, 1, sec_buf) != 1) {
+			printf(" ** zfs_devread() read error - last part\n");
+			return 1;
+		}
+		memcpy(buf, sec_buf, byte_len);
+	}
+	return 0;
+}
diff --git a/include/zfs_common.h b/include/zfs_common.h
index 04e73d0..e2fcaaf 100644
--- a/include/zfs_common.h
+++ b/include/zfs_common.h
@@ -22,6 +22,10 @@
 #ifndef __ZFS_COMMON__
 #define __ZFS_COMMON__
 
+#ifdef CONFIG_DM
+#include <dm/structures.h>
+#endif
+
 #define SECTOR_SIZE			0x200
 #define SECTOR_BITS			9
 
@@ -103,7 +107,11 @@ int zfs_close(zfs_file_t);
 int zfs_ls(device_t dev, const char *path,
 		   int (*hook) (const char *, const struct zfs_dirhook_info *));
 int zfs_devread(int sector, int byte_offset, int byte_len, char *buf);
+#ifdef CONFIG_DM
+int zfs_set_blk_dev(struct instance *dev);
+#else
 int zfs_set_blk_dev(block_dev_desc_t *rbdd, int part);
+#endif
 void zfs_unmount(struct zfs_data *data);
 int lzjb_decompress(void *, void *, uint32_t, uint32_t);
 #endif
-- 
1.7.12



More information about the U-Boot mailing list