Uboot文件系统框架概述
8. 文件系统
uboot 支持多种常见的文件系统,包括 fat 、 ext 、 jffs2 、 reiserfs 、 yaffs2 、 zfs 、ubifs 、cbfs 、cramfs 等。
uboot 的文件系统有两种接口,一种是 fs_*
一种是具体的文件系统的接口,比如 yaffs2 的接口就是 yaffs_*
。
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 操作函数)。
- 具体的文件系统
具体的文件系统就比较简单,都提供 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 的文件系统部分基本就是这两类,本身并不复杂,麻烦在于具体的文件系统实现:文件系统逻辑和存储设备操作接口。(此不赘述)