From patchwork Thu Oct 11 18:59:29 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stephen Warren X-Patchwork-Id: 190971 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 0B1DF2C032B for ; Fri, 12 Oct 2012 06:00:13 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5F35E4A029; Thu, 11 Oct 2012 21:00:06 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hrRKozniotq4; Thu, 11 Oct 2012 21:00:06 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 98A7C4A02A; Thu, 11 Oct 2012 20:59:49 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4AD444A01B for ; Thu, 11 Oct 2012 20:59:44 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ObvZQMcAm6yY for ; Thu, 11 Oct 2012 20:59:42 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from avon.wwwdotorg.org (avon.wwwdotorg.org [70.85.31.133]) by theia.denx.de (Postfix) with ESMTPS id 08D124A01E for ; Thu, 11 Oct 2012 20:59:39 +0200 (CEST) Received: from severn.wwwdotorg.org (unknown [192.168.65.5]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by avon.wwwdotorg.org (Postfix) with ESMTPS id 000396229; Thu, 11 Oct 2012 12:59:51 -0600 (MDT) Received: from localhost.localdomain (localhost [127.0.0.1]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by severn.wwwdotorg.org (Postfix) with ESMTPSA id E866CE40F2; Thu, 11 Oct 2012 12:59:36 -0600 (MDT) From: Stephen Warren To: Tom Rini Date: Thu, 11 Oct 2012 12:59:29 -0600 Message-Id: <1349981969-26113-3-git-send-email-swarren@wwwdotorg.org> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1349981969-26113-1-git-send-email-swarren@wwwdotorg.org> References: <1349981969-26113-1-git-send-email-swarren@wwwdotorg.org> X-NVConfidentiality: public X-Virus-Scanned: clamav-milter 0.96.5 at avon.wwwdotorg.org X-Virus-Status: Clean Cc: u-boot@lists.denx.de, Stephen Warren , Rob Herring Subject: [U-Boot] [PATCH V2 3/3] fs: add partition switch libary, implement ls and fsload commands X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Stephen Warren 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. Signed-off-by: Stephen Warren Reviewed-by: Benoît Thébaudeau --- 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 . + */ + +#include +#include +#include + +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", + " [] [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 /)", + " [] [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@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 . + */ + +#include +#include +#include +#include +#include +#include + +#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 . + */ +#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 */