[U-Boot] [PATCH 07/11] DM: use new blockdev API in FAT

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


cmd_fatdm.c is a copy of cmd_fat.c with just trivaial 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    |   4 ++
 common/cmd_fatdm.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/fat/Makefile    |   7 +-
 fs/fat/dev_dm.c    | 141 +++++++++++++++++++++++++++++++++++++++
 include/fat.h      |   8 +++
 5 files changed, 351 insertions(+), 1 deletion(-)
 create mode 100644 common/cmd_fatdm.c
 create mode 100644 fs/fat/dev_dm.c

diff --git a/common/Makefile b/common/Makefile
index aa09f17..29e5798 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -88,7 +88,11 @@ COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
 COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
 COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
 COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
+ifdef CONFIG_DM
+COBJS-$(CONFIG_CMD_FAT) += cmd_fatdm.o
+else
 COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
+endif
 COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o
 COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
 COBJS-$(CONFIG_CMD_FDOS) += cmd_fdos.o
diff --git a/common/cmd_fatdm.c b/common/cmd_fatdm.c
new file mode 100644
index 0000000..d91c53f
--- /dev/null
+++ b/common/cmd_fatdm.c
@@ -0,0 +1,192 @@
+/*
+ * (C) Copyright 2002
+ * Richard Jones, rjones at nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+/*
+ * Boot support
+ */
+#include <common.h>
+#include <command.h>
+#include <s_record.h>
+#include <net.h>
+#include <ata.h>
+#include <part.h>
+#include <fat.h>
+#include <dm/structures.h>
+#include <dm/blockdev.h>
+
+int do_fat_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	long size;
+	unsigned long offset;
+	unsigned long count;
+	char buf[12];
+	struct instance *bdev;
+
+	if (argc < 4)
+		return CMD_RET_USAGE;
+
+	bdev = get_blockdev_by_name(argv[1]);
+	if (!bdev) {
+		puts("\n** Invalid boot device **\n");
+		return -EINVAL;
+	}
+	if (fat_register_device(bdev)) {
+		printf("\n** Unable to use %s for fatload **\n", argv[1]);
+		return -EINVAL;
+	}
+	offset = simple_strtoul(argv[2], NULL, 16);
+	if (argc == 5)
+		count = simple_strtoul(argv[5], NULL, 16);
+	else
+		count = 0;
+	size = file_fat_read(argv[3], (unsigned char *)offset, count);
+
+	if (size == -1) {
+		printf("\n** Unable to read \"%s\" from %s **\n",
+			argv[3], argv[1]);
+		return -EIO;
+	}
+
+	printf("\n%ld bytes read\n", size);
+
+	sprintf(buf, "%lX", size);
+	setenv("filesize", buf);
+
+	return 0;
+}
+
+
+U_BOOT_CMD(
+	fatload,	6,	0,	do_fat_fsload,
+	"load binary file from a dos filesystem",
+	"<dev[:part]> <addr> <filename> [bytes]\n"
+	"    - load binary file 'filename' from 'dev'\n"
+	"      to address 'addr' from dos filesystem"
+);
+
+int do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *filename = "/";
+	int ret;
+	struct instance *bdev;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	bdev = get_blockdev_by_name(argv[1]);
+	if (!bdev) {
+		puts("\n** Invalid boot device **\n");
+		return -EINVAL;
+	}
+	if (fat_register_device(bdev)) {
+		printf("\n** Unable to use %s for fatls **\n", argv[1]);
+		return -EINVAL;
+	}
+	if (argc == 3)
+		ret = file_fat_ls(argv[2]);
+	else
+		ret = file_fat_ls(filename);
+
+	if (ret != 0)
+		printf("No Fat FS detected\n");
+	return ret;
+}
+
+U_BOOT_CMD(
+	fatls,	3,	1,	do_fat_ls,
+	"list files in a directory (default /)",
+	"<dev[:part]> [directory]\n"
+	"    - list files from 'dev' in a 'directory'"
+);
+
+int do_fat_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct instance *bdev;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	bdev = get_blockdev_by_name(argv[1]);
+	if (!bdev) {
+		puts("\n** Invalid boot device **\n");
+		return -EINVAL;
+	}
+	if (fat_register_device(bdev)) {
+		printf("\n** Unable to use %s for fatinfo **\n", argv[1]);
+		return -EIO;
+	}
+	return file_fat_detectfs();
+}
+
+U_BOOT_CMD(
+	fatinfo,	2,	1,	do_fat_fsinfo,
+	"print information about filesystem",
+	"<dev[:part]>\n"
+	"    - print information about filesystem from 'dev' on 'interface'"
+);
+
+#ifdef CONFIG_FAT_WRITE
+static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
+		int argc, char * const argv[])
+{
+	long size;
+	unsigned long addr;
+	unsigned long count;
+	struct instance *bdev;
+
+	if (argc < 4)
+		return CMD_RET_USAGE;
+
+	bdev = get_blockdev_by_name(argv[1]);
+	if (!bdev) {
+		puts("\n** Invalid boot device **\n");
+		return 1;
+	}
+	if (fat_register_device(bdev)) {
+		printf("\n** Unable to use %s for fatwrite **\n",
+			argv[1]);
+		return 1;
+	}
+	addr = simple_strtoul(argv[2], NULL, 16);
+	count = simple_strtoul(argv[4], NULL, 16);
+
+	size = file_fat_write(argv[3], (void *)addr, count);
+	if (size == -1) {
+		printf("\n** Unable to write \"%s\" to %s **\n",
+			argv[3], argv[1]);
+		return 1;
+	}
+
+	printf("%ld bytes written\n", size);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	fatwrite,	6,	0,	do_fat_fswrite,
+	"write file into a dos filesystem",
+	"<dev[:part]> <addr> <filename> <bytes>\n"
+	"    - write file 'filename' from the address 'addr' in RAM\n"
+	"      to 'dev' on 'interface'"
+);
+#endif
diff --git a/fs/fat/Makefile b/fs/fat/Makefile
index 176e6f4..f85480c 100644
--- a/fs/fat/Makefile
+++ b/fs/fat/Makefile
@@ -24,8 +24,13 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libfat.o
 
 AOBJS	=
-COBJS-$(CONFIG_CMD_FAT)	:= fat.o dev.o
+COBJS-$(CONFIG_CMD_FAT)	:= fat.o
 COBJS-$(CONFIG_FAT_WRITE) := fat_write.o
+ifdef CONFIG_DM
+COBJS-$(CONFIG_CMD_FAT)	+= dev_dm.o
+else
+COBJS-$(CONFIG_CMD_FAT)	+= dev.o
+endif
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_CMD_FAT)	+= file.o
diff --git a/fs/fat/dev_dm.c b/fs/fat/dev_dm.c
new file mode 100644
index 0000000..3f66e54
--- /dev/null
+++ b/fs/fat/dev_dm.c
@@ -0,0 +1,141 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis at gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <dm/structures.h>
+#include <dm/blockdev.h>
+#include <fat.h>
+#include <errno.h>
+
+static struct instance *bdev;
+
+#define DOS_BOOT_MAGIC_OFFSET   0x1fe
+#define DOS_FS_TYPE_OFFSET      0x36
+#define DOS_FS32_TYPE_OFFSET    0x52
+
+int fat_disk_read(__u32 block, __u32 nr_blocks, void *buf)
+{
+	if (!bdev)
+		return -1;
+
+	return blockdev_read(bdev, block, nr_blocks, buf);
+}
+
+int fat_disk_write(__u32 block, __u32 nr_blocks, void *buf)
+{
+	if (!bdev)
+		return -1;
+
+	return blockdev_write(bdev, block, nr_blocks, buf);
+}
+
+int fat_get_blksz(void)
+{
+	struct option op;
+	int error;
+
+	error = blockdev_get_option(bdev, BLKD_OPT_BLOCKSIZE, &op);
+	if ((error) || (OPTION_TYPE(op) != OPTION_TYPE_U))
+		return -EINVAL;
+
+	return op.data.data_u;
+}
+
+int fat_get_partsize(void)
+{
+	struct option op;
+	int error;
+
+	error = blockdev_get_option(bdev, BLKD_OPT_BLOCKCOUNT, &op);
+	if ((error) || (OPTION_TYPE(op) != OPTION_TYPE_U))
+		return -EINVAL;
+
+	return op.data.data_u;
+}
+
+int fat_register_device(struct instance *dev)
+{
+	int blksz;
+
+	if (!dev)
+		return -EINVAL;
+
+	bdev = dev;
+	blksz = fat_get_blksz();
+	if (blksz < 0) {
+		/*this should not happen, lets just warn and guess */
+		printf("Error reading device block size!!!\nGuessing 512\n");
+		blksz = 512;
+	}
+	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, blksz);
+
+	/* Make sure it has a valid FAT header */
+	if (fat_disk_read(0, 1, buffer) != 1) {
+		bdev = NULL;
+		return -EIO;
+	}
+
+	/* Check if it's actually a DOS volume */
+	if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) {
+		bdev = NULL;
+		return -ENOENT;
+	}
+
+	/* Check for FAT12/FAT16/FAT32 filesystem */
+	if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3))
+		return 0;
+	if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5))
+		return 0;
+
+	bdev = NULL;
+	return -EINVAL;
+
+}
+
+int file_fat_detectfs(void)
+{
+	boot_sector bs;
+	volume_info volinfo;
+	int fatsize;
+	char vol_label[12];
+
+	if (!bdev) {
+		printf("No current device\n");
+		return -EINVAL;
+	}
+
+	print_blockdev_info(bdev);
+
+	if (fat_read_bootsectandvi(&bs, &volinfo, &fatsize)) {
+		printf("\nNo valid FAT fs found\n");
+		return -EINVAL;
+	}
+
+	memcpy(vol_label, volinfo.volume_label, 11);
+	vol_label[11] = '\0';
+	volinfo.fs_type[5] = '\0';
+
+	printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label);
+
+	return 0;
+}
+
diff --git a/include/fat.h b/include/fat.h
index 98f77a5..85f2f0b 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -29,6 +29,10 @@
 
 #include <asm/byteorder.h>
 
+#ifdef CONFIG_DM
+#include <dm/structures.h>
+#endif
+
 #define CONFIG_SUPPORT_VFAT
 /* Maximum Long File Name length supported here is 128 UTF-16 code units */
 #define VFAT_MAXLEN_BYTES	256 /* Maximum LFN buffer in bytes */
@@ -210,7 +214,11 @@ int file_fat_detectfs(void);
 int file_fat_ls(const char *dir);
 long file_fat_read(const char *filename, void *buffer, unsigned long maxsize);
 const char *file_getfsname(int idx);
+#ifdef CONFIG_DM
+int fat_register_device(struct instance *dev);
+#else
 int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
+#endif
 
 int file_fat_write(const char *filename, void *buffer, unsigned long maxsize);
 
-- 
1.7.12



More information about the U-Boot mailing list