请稍侯

Uboot文件系统框架概述

8. 文件系统

uboot 支持多种常见的文件系统,包括 fat 、 ext 、 jffs2 、 reiserfs 、 yaffs2 、 zfs 、ubifs 、cbfs 、cramfs 等。

uboot 的文件系统有两种接口,一种是 fs_* 一种是具体的文件系统的接口,比如 yaffs2 的接口就是 yaffs_*

  1. fs_*

fs_* 实际上是对各种文件系统的封装,在 fs/fs.c 里定义了一个 fstype 类型的数组:

static struct fstype_info fstypes[] = {
#ifdef CONFIG_FS_FAT
    {
        .fstype = FS_TYPE_FAT,
        .name = "fat",
        .null_dev_desc_ok = false,
        .probe = fat_set_blk_dev,
        .close = fat_close,
        .ls = file_fat_ls,
        .exists = fat_exists,
        .size = fat_size,
        .read = fat_read_file,
#ifdef CONFIG_FAT_WRITE
        .write = file_fat_write,
#else
        .write = fs_write_unsupported,
#endif
        .uuid = fs_uuid_unsupported,
    },
#endif
#ifdef CONFIG_FS_EXT4
    {
        .fstype = FS_TYPE_EXT,
        .name = "ext4",
        .null_dev_desc_ok = false,
        .probe = ext4fs_probe,
        .close = ext4fs_close,
        .ls = ext4fs_ls,
        .exists = ext4fs_exists,
        .size = ext4fs_size,
        .read = ext4_read_file,
#ifdef CONFIG_CMD_EXT4_WRITE
        .write = ext4_write_file,
#else
        .write = fs_write_unsupported,
#endif
        .uuid = ext4fs_uuid,
    },
#endif
#ifdef CONFIG_SANDBOX
    {
        .fstype = FS_TYPE_SANDBOX,
        .name = "sandbox",
        .null_dev_desc_ok = true,
        .probe = sandbox_fs_set_blk_dev,
        .close = sandbox_fs_close,
        .ls = sandbox_fs_ls,
        .exists = sandbox_fs_exists,
        .size = sandbox_fs_size,
        .read = fs_read_sandbox,
        .write = fs_write_sandbox,
        .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",
        .null_dev_desc_ok = true,
        .probe = fs_probe_unsupported,
        .close = fs_close_unsupported,
        .ls = fs_ls_unsupported,
        .exists = fs_exists_unsupported,
        .size = fs_size_unsupported,
        .read = fs_read_unsupported,
        .write = fs_write_unsupported,
        .uuid = fs_uuid_unsupported,
    },
};

数组内包含了几种文件系统:fat 、 ext4 、ubifs 和实验用的 sandbox,而 fs 的接口函数,如 fs_read()fs_write()fs_ls 等,在执行操作时都是根据文件系统的类型调用不同文件系统接口:

int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len,
	    loff_t *actread)
{
	struct fstype_info *info = fs_get_info(fs_type);
...
	ret = info->read(filename, buf, offset, len, actread);
...
	fs_close();

	return ret;
}

其它操作也类似,首先根据文件系统类型(fs_type)获取到具体某个文件系统操作的数据结构(fs_get_info()),然后调用指定的操作(info->read()),最后关闭文件(fs_close()uboot 的文件系统操作都是一次性的,即将open->ops->close 集成为一个 ops 操作函数)。

  1. 具体的文件系统

具体的文件系统就比较简单,都提供 read 、 write 、 ls 接口(如上所述,uboot 不提供也不需要提供单独的 open 、 close 接口)。如 jffs2 的 read 接口:

/* Load a file from flash into memory. fname can be a full path */
u32
jffs2_1pass_load(char *dest, struct part_info * part, const char *fname)
{

	struct b_lists *pl;
	long ret = 1;
	u32 inode;

	if (! (pl  = jffs2_get_list(part, "load")))
		return 0;

	if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) {
		putstr("load: Failed to find inode\r\n");
		return 0;
	}

	/* Resolve symlinks */
	if (! (inode = jffs2_1pass_resolve_inode(pl, inode))) {
		putstr("load: Failed to resolve inode structure\r\n");
		return 0;
	}

	if ((ret = jffs2_1pass_read_inode(pl, inode, dest)) < 0) {
		putstr("load: Failed to read inode\r\n");
		return 0;
	}

	DEBUGF ("load: loaded '%s' to 0x%lx (%ld bytes)\n", fname,
				(unsigned long) dest, ret);
	return ret;
}

fat 的 write 接口:

int file_fat_write(const char *filename, void *buffer, loff_t offset,
		   loff_t maxsize, loff_t *actwrite)
{
	if (offset != 0) {
		printf("Error: non zero offset is currently not supported.\n");
		return -1;
	}

	printf("writing %s\n", filename);
	return do_fat_write(filename, buffer, maxsize, actwrite);
}

ext4 的 ls 接口 :

int ext4fs_ls(const char *dirname)
{
	struct ext2fs_node *dirnode;
	int status;

	if (dirname == NULL)
		return 0;

	status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
				  FILETYPE_DIRECTORY);
	if (status != 1) {
		printf("** Can not find directory. **\n");
		return 1;
	}

	ext4fs_iterate_dir(dirnode, NULL, NULL, NULL);
	ext4fs_free_node(dirnode, &ext4fs_root->diropen);

	return 0;
}

uboot 的文件系统部分基本就是这两类,本身并不复杂,麻烦在于具体的文件系统实现:文件系统逻辑和存储设备操作接口。(此不赘述)