[U-Boot] [PATCH V2 3/3] fs: add partition switch libary, implement ls and fsload commands

Rob Herring robherring2 at gmail.com
Mon Oct 15 18:33:17 CEST 2012


On 10/11/2012 01:59 PM, Stephen Warren wrote:
> From: Stephen Warren <swarren at nvidia.com>
> 
> Implement "ls" and "fsload" commands that act like {fat,ext2}{ls,load},
> and transparently handle either file-system. This scheme could easily be
> extended to other filesystem types; I only didn't do it for zfs because
> I don't have any filesystems of that type to test with.
> 

This is exactly what I want to get to. However, I think the first step
should be to unify the filesystem api similar to the block device api.
This would avoid the wrapper here and yet another copy of nearly
identical code. Then we can unify the implementations of *ls and *load.

Rob

> Signed-off-by: Stephen Warren <swarren at nvidia.com>
> ---
> v2:
> * Build cmd_fs.c when CONFIG_CMD_FS_GENERIC not always.
> * Use new CONFIG_FS_{FAT,EXT4} rather than CONFIG_CMD_{FAT,EXT2}.
> * Implemented fs_close() and call it from the tail of fs_ls() and fs_read().
>   This ensures that any other usage of e.g. the ext4 library between fs_*()
>   calls, then the two usages won't interfere.
> * Re-organized fs.c to reduce the number of ifdef blocks.
> * Added argc checking to do_ls().
> ---
>  Makefile        |    3 +-
>  common/Makefile |    1 +
>  common/cmd_fs.c |   89 ++++++++++++++++++++++
>  fs/Makefile     |   47 +++++++++++
>  fs/fs.c         |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/fs.h    |   49 ++++++++++++
>  6 files changed, 415 insertions(+), 1 deletions(-)
>  create mode 100644 common/cmd_fs.c
>  create mode 100644 fs/Makefile
>  create mode 100644 fs/fs.c
>  create mode 100644 include/fs.h
> 
> diff --git a/Makefile b/Makefile
> index d7e2c2f..0b50eb7 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -242,7 +242,8 @@ LIBS-y += drivers/net/npe/libnpe.o
>  endif
>  LIBS-$(CONFIG_OF_EMBED) += dts/libdts.o
>  LIBS-y += arch/$(ARCH)/lib/lib$(ARCH).o
> -LIBS-y += fs/cramfs/libcramfs.o \
> +LIBS-y += fs/libfs.o \
> +	fs/cramfs/libcramfs.o \
>  	fs/ext4/libext4fs.o \
>  	fs/fat/libfat.o \
>  	fs/fdos/libfdos.o \
> diff --git a/common/Makefile b/common/Makefile
> index 125b2be..c6c31f7 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -103,6 +103,7 @@ COBJS-$(CONFIG_CMD_FLASH) += cmd_flash.o
>  ifdef CONFIG_FPGA
>  COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
>  endif
> +COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
>  COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o
>  COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
>  COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o
> diff --git a/common/cmd_fs.c b/common/cmd_fs.c
> new file mode 100644
> index 0000000..9df0a66
> --- /dev/null
> +++ b/common/cmd_fs.c
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
> + *
> + * Inspired by cmd_ext_common.c, cmd_fat.c.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <fs.h>
> +
> +int do_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	unsigned long addr;
> +	unsigned long bytes;
> +	unsigned long pos;
> +	int len_read;
> +	char buf[12];
> +
> +	if (argc < 5)
> +		return CMD_RET_USAGE;
> +
> +	if (fs_set_blk_dev(argv[1], argv[2]))
> +		return 1;
> +
> +	addr = simple_strtoul(argv[3], NULL, 0);
> +	if (argc >= 6)
> +		bytes = simple_strtoul(argv[5], NULL, 0);
> +	else
> +		bytes = 0;
> +	if (argc >= 7)
> +		pos = simple_strtoul(argv[6], NULL, 0);
> +	else
> +		pos = 0;
> +
> +	len_read = fs_read(argv[4], addr, pos, bytes);
> +	if (len_read <= 0)
> +		return 1;
> +
> +	sprintf(buf, "0x%x", (unsigned int)len_read);
> +	setenv("filesize", buf);
> +
> +	return 0;
> +}
> +
> +U_BOOT_CMD(
> +	fsload,	7,	0,	do_fsload,
> +	"load binary file from a filesystem",
> +	"<interface> [<dev[:part]>] <addr> <filename> [bytes [pos]]\n"
> +	"    - Load binary file 'filename' from partition 'part' on device\n"
> +	"       type 'interface' instance 'dev' to address 'addr' in memory.\n"
> +	"      'bytes' gives the size to load in bytes.\n"
> +	"      If 'bytes' is 0 or omitted, the file is read until the end.\n"
> +	"      'pos' gives the file byte position to start reading from.\n"
> +	"      If 'pos' is 0 or omitted, the file is read from the start."
> +);
> +
> +int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	if (argc < 2)
> +		return CMD_RET_USAGE;
> +
> +	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL))
> +		return 1;
> +
> +	if (fs_ls(argc == 4 ? argv[3] : "/"))
> +		return 1;
> +
> +	return 0;
> +}
> +
> +U_BOOT_CMD(
> +	ls,	4,	1,	do_ls,
> +	"list files in a directory (default /)",
> +	"<interface> [<dev[:part]>] [directory]\n"
> +	"    - List files in directory 'directory' of partition 'part' on\n"
> +	"      device type 'interface' instance 'dev'."
> +);
> diff --git a/fs/Makefile b/fs/Makefile
> new file mode 100644
> index 0000000..d0ab3ae
> --- /dev/null
> +++ b/fs/Makefile
> @@ -0,0 +1,47 @@
> +#
> +# (C) Copyright 2000-2006
> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> +# Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
> +#
> +# 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 $(TOPDIR)/config.mk
> +
> +LIB	= $(obj)libfs.o
> +
> +COBJS-y				+= fs.o
> +
> +COBJS	:= $(COBJS-y)
> +SRCS	:= $(COBJS:.o=.c)
> +OBJS	:= $(addprefix $(obj),$(COBJS))
> +
> +all:	$(LIB)
> +
> +$(LIB):	$(obj).depend $(OBJS)
> +	$(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/fs/fs.c b/fs/fs.c
> new file mode 100644
> index 0000000..18cfaff
> --- /dev/null
> +++ b/fs/fs.c
> @@ -0,0 +1,227 @@
> +/*
> + * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <part.h>
> +#include <ext4fs.h>
> +#include <fat.h>
> +#include <fs.h>
> +
> +#define FS_TYPE_INVALID	0
> +#define FS_TYPE_FAT	1
> +#define FS_TYPE_EXT	2
> +
> +static block_dev_desc_t *fs_dev_desc;
> +static disk_partition_t fs_partition;
> +static int fs_type = FS_TYPE_INVALID;
> +
> +static inline int fs_ls_unsupported(const char *dirname)
> +{
> +	printf("** Unrecognized filesystem type **\n");
> +	return -1;
> +}
> +
> +static inline int fs_read_unsupported(const char *filename, ulong addr,
> +				      int offset, int len)
> +{
> +	printf("** Unrecognized filesystem type **\n");
> +	return -1;
> +}
> +
> +#ifdef CONFIG_FS_FAT
> +static int fs_probe_fat(void)
> +{
> +	return fat_set_blk_dev(fs_dev_desc, &fs_partition);
> +}
> +
> +static void fs_close_fat(void)
> +{
> +}
> +
> +#define fs_ls_fat file_fat_ls
> +
> +static int fs_read_fat(const char *filename, ulong addr, int offset, int len)
> +{
> +	int len_read;
> +
> +	len_read = file_fat_read_at(filename, offset,
> +				    (unsigned char *)addr, len);
> +	if (len_read == -1) {
> +		printf("** Unable to read file %s **\n", filename);
> +		return -1;
> +	}
> +
> +	return len_read;
> +}
> +#else
> +static inline int fs_probe_fat(void)
> +{
> +	return -1;
> +}
> +
> +static inline void fs_close_fat(void)
> +{
> +}
> +
> +#define fs_ls_fat fs_ls_unsupported
> +#define fs_read_fat fs_read_unsupported
> +#endif
> +
> +#ifdef CONFIG_FS_EXT4
> +static int fs_probe_ext(void)
> +{
> +	ext4fs_set_blk_dev(fs_dev_desc, &fs_partition);
> +
> +	if (!ext4fs_mount(fs_partition.size)) {
> +		ext4fs_close();
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static void fs_close_ext(void)
> +{
> +	ext4fs_close();
> +}
> +
> +#define fs_ls_ext ext4fs_ls
> +
> +static int fs_read_ext(const char *filename, ulong addr, int offset, int len)
> +{
> +	int file_len;
> +	int len_read;
> +
> +	if (offset != 0) {
> +		printf("** Cannot support non-zero offset **\n");
> +		return -1;
> +	}
> +
> +	file_len = ext4fs_open(filename);
> +	if (file_len < 0) {
> +		printf("** File not found %s **\n", filename);
> +		ext4fs_close();
> +		return -1;
> +	}
> +
> +	if (len == 0)
> +		len = file_len;
> +
> +	len_read = ext4fs_read((char *)addr, len);
> +	ext4fs_close();
> +
> +	if (len_read != len) {
> +		printf("** Unable to read file %s **\n", filename);
> +		return -1;
> +	}
> +
> +	return len_read;
> +}
> +#else
> +static inline int fs_probe_ext(void)
> +{
> +	return -1;
> +}
> +
> +static inline void fs_close_ext(void)
> +{
> +}
> +
> +#define fs_ls_ext fs_ls_unsupported
> +#define fs_read_ext fs_read_unsupported
> +#endif
> +
> +int fs_set_blk_dev(const char *ifname, const char *dev_part_str)
> +{
> +	int part;
> +
> +	part = get_device_and_partition(ifname, dev_part_str, &fs_dev_desc,
> +					&fs_partition, 1);
> +	if (part < 0)
> +		return -1;
> +
> +	if (!fs_probe_fat()) {
> +		fs_type = FS_TYPE_FAT;
> +		return 0;
> +	}
> +
> +	if (!fs_probe_ext()) {
> +		fs_type = FS_TYPE_EXT;
> +		return 0;
> +	}
> +
> +	printf("** Unrecognized filesystem type **\n");
> +	return -1;
> +}
> +
> +static void fs_close(void)
> +{
> +	switch (fs_type) {
> +	case FS_TYPE_FAT:
> +		fs_close_fat();
> +		break;
> +	case FS_TYPE_EXT:
> +		fs_close_ext();
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	fs_type = FS_TYPE_INVALID;
> +}
> +
> +int fs_ls(const char *dirname)
> +{
> +	int ret;
> +
> +	switch (fs_type) {
> +	case FS_TYPE_FAT:
> +		ret = fs_ls_fat(dirname);
> +		break;
> +	case FS_TYPE_EXT:
> +		ret = fs_ls_ext(dirname);
> +		break;
> +	default:
> +		ret = fs_ls_unsupported(dirname);
> +		break;
> +	}
> +
> +	fs_close();
> +
> +	return ret;
> +}
> +
> +int fs_read(const char *filename, ulong addr, int offset, int len)
> +{
> +	int ret;
> +
> +	switch (fs_type) {
> +	case FS_TYPE_FAT:
> +		ret = fs_read_fat(filename, addr, offset, len);
> +		break;
> +	case FS_TYPE_EXT:
> +		ret = fs_read_ext(filename, addr, offset, len);
> +		break;
> +	default:
> +		ret = fs_read_unsupported(filename, addr, offset, len);
> +		break;
> +	}
> +
> +	fs_close();
> +
> +	return ret;
> +}
> diff --git a/include/fs.h b/include/fs.h
> new file mode 100644
> index 0000000..a0fda28
> --- /dev/null
> +++ b/include/fs.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
> + */
> +#ifndef _FS_H
> +#define _FS_H
> +
> +/*
> + * Tell the fs layer which block device an partition to use for future
> + * commands. This also internally identifies the filesystem that is present
> + * within the partition.
> + *
> + * Returns 0 on success.
> + * Returns non-zero if there is an error accessing the disk or partition, or
> + * no known filesystem type could be recognized on it.
> + */
> +int fs_set_blk_dev(const char *ifname, const char *dev_part_str);
> +
> +/*
> + * Print the list of files on the partition previously set by fs_set_blk_dev(),
> + * in directory "dirname".
> + *
> + * Returns 0 on success. Returns non-zero on error.
> + */
> +int fs_ls(const char *dirname);
> +
> +/*
> + * Read file "filename" from the partition previously set by fs_set_blk_dev(),
> + * to address "addr", starting at byte offset "offset", and reading "len"
> + * bytes. "offset" may be 0 to read from the start of the file. "len" may be
> + * 0 to read the entire file. Note that not all filesystem types support
> + * either/both offset!=0 or len!=0.
> + *
> + * Returns number of bytes read on success. Returns <= 0 on error.
> + */
> +int fs_read(const char *filename, ulong addr, int offset, int len);
> +
> +#endif /* _FS_H */
> 



More information about the U-Boot mailing list