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