
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@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@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