[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