[U-Boot] [PATCH v2 0/3] ubifs: Add generic fs support

Hi Tom, Heiko,
Here is v2 of my ubifs generic fs support series.
Changes since v1: -Use a helper function instead of exporting the ubifs_mounted variable.
Regards,
Hans

Modify the ubifs u-boot wrapper function prototypes for generic fs use, and give them their own header file.
This is a preparation patch for adding ubifs support to the generic fs code from fs/fs.c.
Signed-off-by: Hans de Goede hdegoede@redhat.com Reviewed-by: Heiko Schocher hs@denx.de --- common/cmd_ubifs.c | 12 ++------- fs/ubifs/ubifs.c | 70 ++++++++++++++++++++++++++++++++++++++++----------- fs/ubifs/ubifs.h | 6 +---- include/ubifs_uboot.h | 28 +++++++++++++++++++++ 4 files changed, 87 insertions(+), 29 deletions(-) create mode 100644 include/ubifs_uboot.h
diff --git a/common/cmd_ubifs.c b/common/cmd_ubifs.c index 8e9a4e5..5e9d357 100644 --- a/common/cmd_ubifs.c +++ b/common/cmd_ubifs.c @@ -15,8 +15,7 @@ #include <common.h> #include <config.h> #include <command.h> - -#include "../fs/ubifs/ubifs.h" +#include <ubifs_uboot.h>
static int ubifs_initialized; static int ubifs_mounted; @@ -54,14 +53,7 @@ int ubifs_is_mounted(void)
void cmd_ubifs_umount(void) { - - if (ubifs_sb) { - printf("Unmounting UBIFS volume %s!\n", - ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name); - ubifs_umount(ubifs_sb->s_fs_info); - } - - ubifs_sb = NULL; + uboot_ubifs_umount(); ubifs_mounted = 0; ubifs_initialized = 0; } diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 4daa7fa..04e9a21 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -568,7 +568,7 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) return 0; }
-int ubifs_ls(char *filename) +int ubifs_ls(const char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; struct file *file; @@ -579,7 +579,7 @@ int ubifs_ls(char *filename) int ret = 0;
c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); - inum = ubifs_findfile(ubifs_sb, filename); + inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { ret = -1; goto out; @@ -785,7 +785,8 @@ error: return err; }
-int ubifs_load(char *filename, u32 addr, u32 size) +int ubifs_read(const char *filename, void *buf, loff_t offset, + loff_t size, loff_t *actread) { struct ubifs_info *c = ubifs_sb->s_fs_info; unsigned long inum; @@ -796,10 +797,18 @@ int ubifs_load(char *filename, u32 addr, u32 size) int count; int last_block_size = 0;
+ *actread = 0; + + if (offset & (PAGE_SIZE - 1)) { + printf("ubifs: Error offset must be a multple of %d\n", + PAGE_SIZE); + return -1; + } + c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get * the real file here */ - inum = ubifs_findfile(ubifs_sb, filename); + inum = ubifs_findfile(ubifs_sb, (char *)filename); if (!inum) { err = -1; goto out; @@ -815,19 +824,24 @@ int ubifs_load(char *filename, u32 addr, u32 size) goto out; }
+ if (offset > inode->i_size) { + printf("ubifs: Error offset (%lld) > file-size (%lld)\n", + offset, size); + err = -1; + goto put_inode; + } + /* * If no size was specified or if size bigger than filesize * set size to filesize */ - if ((size == 0) || (size > inode->i_size)) - size = inode->i_size; + if ((size == 0) || (size > (inode->i_size - offset))) + size = inode->i_size - offset;
count = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; - printf("Loading file '%s' to addr 0x%08x with size %d (0x%08x)...\n", - filename, addr, size, size);
- page.addr = (void *)addr; - page.index = 0; + page.addr = buf; + page.index = offset / PAGE_SIZE; page.inode = inode; for (i = 0; i < count; i++) { /* @@ -844,16 +858,44 @@ int ubifs_load(char *filename, u32 addr, u32 size) page.index++; }
- if (err) + if (err) { printf("Error reading file '%s'\n", filename); - else { - setenv_hex("filesize", size); - printf("Done\n"); + *actread = i * PAGE_SIZE; + } else { + *actread = size; }
+put_inode: ubifs_iput(inode);
out: ubi_close_volume(c->ubi); return err; } + +/* Compat wrappers for common/cmd_ubifs.c */ +int ubifs_load(char *filename, u32 addr, u32 size) +{ + loff_t actread; + int err; + + printf("Loading file '%s' to addr 0x%08x...\n", filename, addr); + + err = ubifs_read(filename, (void *)addr, 0, size, &actread); + if (err == 0) { + setenv_hex("filesize", actread); + printf("Done\n"); + } + + return err; +} + +void uboot_ubifs_umount(void) +{ + if (ubifs_sb) { + printf("Unmounting UBIFS volume %s!\n", + ((struct ubifs_info *)(ubifs_sb->s_fs_info))->vi.name); + ubifs_umount(ubifs_sb->s_fs_info); + ubifs_sb = NULL; + } +} diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index a51b237..225965c 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -34,6 +34,7 @@ #include <asm/atomic.h> #include <asm-generic/atomic-long.h> #include <ubi_uboot.h> +#include <ubifs_uboot.h>
#include <linux/ctype.h> #include <linux/time.h> @@ -2379,11 +2380,6 @@ int ubifs_decompress(const void *buf, int len, void *out, int *out_len, #include "key.h"
#ifdef __UBOOT__ -/* these are used in cmd_ubifs.c */ -int ubifs_init(void); -int uboot_ubifs_mount(char *vol_name); void ubifs_umount(struct ubifs_info *c); -int ubifs_ls(char *dir_name); -int ubifs_load(char *filename, u32 addr, u32 size); #endif #endif /* !__UBIFS_H__ */ diff --git a/include/ubifs_uboot.h b/include/ubifs_uboot.h new file mode 100644 index 0000000..3e0cd72 --- /dev/null +++ b/include/ubifs_uboot.h @@ -0,0 +1,28 @@ +/* + * UBIFS u-boot wrapper functions header + * + * Copyright (C) 2006-2008 Nokia Corporation + * + * (C) Copyright 2008-2009 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Authors: Artem Bityutskiy (Битюцкий Артём) + * Adrian Hunter + */ + +#ifndef __UBIFS_UBOOT_H__ +#define __UBIFS_UBOOT_H__ + +int ubifs_init(void); +int uboot_ubifs_mount(char *vol_name); +void uboot_ubifs_umount(void); +int ubifs_is_mounted(void); +int ubifs_load(char *filename, u32 addr, u32 size); + +int ubifs_ls(const char *dir_name); +int ubifs_read(const char *filename, void *buf, loff_t offset, + loff_t size, loff_t *actread); + +#endif /* __UBIFS_UBOOT_H__ */

Implement the necessary functions for implementing generic fs support for ubifs.
Signed-off-by: Hans de Goede hdegoede@redhat.com Reviewed-by: Heiko Schocher hs@denx.de --- fs/ubifs/ubifs.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/ubifs_uboot.h | 4 ++++ 2 files changed, 66 insertions(+)
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 04e9a21..4b064a6 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -568,6 +568,22 @@ static unsigned long ubifs_findfile(struct super_block *sb, char *filename) return 0; }
+int ubifs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info) +{ + /* Check that ubifs is mounted and that we are not being a blkdev */ + if (!ubifs_is_mounted()) { + printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); + return -1; + } + + if (rbdd) { + printf("UBIFS cannot be used with normal block devices\n"); + return -1; + } + + return 0; +} + int ubifs_ls(const char *filename) { struct ubifs_info *c = ubifs_sb->s_fs_info; @@ -616,6 +632,48 @@ out: return ret; }
+int ubifs_exists(const char *filename) +{ + struct ubifs_info *c = ubifs_sb->s_fs_info; + unsigned long inum; + + c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); + inum = ubifs_findfile(ubifs_sb, (char *)filename); + ubi_close_volume(c->ubi); + + return inum != 0; +} + +int ubifs_size(const char *filename, loff_t *size) +{ + struct ubifs_info *c = ubifs_sb->s_fs_info; + unsigned long inum; + struct inode *inode; + int err = 0; + + c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); + + inum = ubifs_findfile(ubifs_sb, (char *)filename); + if (!inum) { + err = -1; + goto out; + } + + inode = ubifs_iget(ubifs_sb, inum); + if (IS_ERR(inode)) { + printf("%s: Error reading inode %ld!\n", __func__, inum); + err = PTR_ERR(inode); + goto out; + } + + *size = inode->i_size; + + ubifs_iput(inode); +out: + ubi_close_volume(c->ubi); + return err; +} + /* * ubifsload... */ @@ -873,6 +931,10 @@ out: return err; }
+void ubifs_close(void) +{ +} + /* Compat wrappers for common/cmd_ubifs.c */ int ubifs_load(char *filename, u32 addr, u32 size) { diff --git a/include/ubifs_uboot.h b/include/ubifs_uboot.h index 3e0cd72..dab433a 100644 --- a/include/ubifs_uboot.h +++ b/include/ubifs_uboot.h @@ -21,8 +21,12 @@ void uboot_ubifs_umount(void); int ubifs_is_mounted(void); int ubifs_load(char *filename, u32 addr, u32 size);
+int ubifs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); int ubifs_ls(const char *dir_name); +int ubifs_exists(const char *filename); +int ubifs_size(const char *filename, loff_t *size); int ubifs_read(const char *filename, void *buf, loff_t offset, loff_t size, loff_t *actread); +void ubifs_close(void);
#endif /* __UBIFS_UBOOT_H__ */

Add generic fs support, so that commands like ls, load and test -e can be used on ubifs.
Signed-off-by: Hans de Goede hdegoede@redhat.com Reviewed-by: Heiko Schocher hs@denx.de --- disk/part.c | 23 +++++++++++++++++++++++ fs/fs.c | 16 ++++++++++++++++ include/fs.h | 1 + 3 files changed, 40 insertions(+)
diff --git a/disk/part.c b/disk/part.c index 43485c9..30f960c 100644 --- a/disk/part.c +++ b/disk/part.c @@ -10,6 +10,7 @@ #include <ide.h> #include <malloc.h> #include <part.h> +#include <ubifs_uboot.h>
#undef PART_DEBUG
@@ -530,6 +531,28 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, return 0; }
+#ifdef CONFIG_CMD_UBIFS + /* + * Special-case ubi, ubi goes through a mtd, rathen then through + * a regular block device. + */ + if (0 == strcmp(ifname, "ubi")) { + if (!ubifs_is_mounted()) { + printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); + return -1; + } + + *dev_desc = NULL; + memset(info, 0, sizeof(*info)); + strcpy((char *)info->type, BOOT_PART_TYPE); + strcpy((char *)info->name, "UBI"); +#ifdef CONFIG_PARTITION_UUIDS + info->uuid[0] = 0; +#endif + return 0; + } +#endif + /* If no dev_part_str, use bootdevice environment variable */ if (!dev_part_str || !strlen(dev_part_str) || !strcmp(dev_part_str, "-")) diff --git a/fs/fs.c b/fs/fs.c index 827b143..b2d6a53 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -23,6 +23,7 @@ #include <fat.h> #include <fs.h> #include <sandboxfs.h> +#include <ubifs_uboot.h> #include <asm/io.h> #include <div64.h> #include <linux/math64.h> @@ -157,6 +158,21 @@ static struct fstype_info fstypes[] = { .uuid = fs_uuid_unsupported, }, #endif +#ifdef CONFIG_CMD_UBIFS + { + .fstype = FS_TYPE_UBIFS, + .name = "ubifs", + .null_dev_desc_ok = true, + .probe = ubifs_set_blk_dev, + .close = ubifs_close, + .ls = ubifs_ls, + .exists = ubifs_exists, + .size = ubifs_size, + .read = ubifs_read, + .write = fs_write_unsupported, + .uuid = fs_uuid_unsupported, + }, +#endif { .fstype = FS_TYPE_ANY, .name = "unsupported", diff --git a/include/fs.h b/include/fs.h index fd1e4ab..059a395 100644 --- a/include/fs.h +++ b/include/fs.h @@ -22,6 +22,7 @@ #define FS_TYPE_FAT 1 #define FS_TYPE_EXT 2 #define FS_TYPE_SANDBOX 3 +#define FS_TYPE_UBIFS 4
/* * Tell the fs layer which block device an partition to use for future
participants (1)
-
Hans de Goede