Files
TencentOS-tiny/components/fs/vfs/tos_vfs_fs.c
daishengdong 0a2d5a4e90 support elfloader for shared object and relocatable object
1. elfloader for shared object
example: TencentOS-tiny\examples\elfloader_shared_object
keil: TencentOS-tiny\board\TencentOS_tiny_EVB_MX_Plus\KEIL\elfloader_shared_object

2. elfloader for relocatable object:
example: TencentOS-tiny\examples\elfloader_relocatable_object
keil: TencentOS-tiny\board\TencentOS_tiny_EVB_MX_Plus\KEIL\elfloader_relocatable_object

3. TODO:
- add icache/dcache flush when module is loaded
- support more relocation type in elfloader_arch_relocate
2020-06-09 19:30:38 +08:00

210 lines
5.5 KiB
C

/*----------------------------------------------------------------------------
* Tencent is pleased to support the open source community by making TencentOS
* available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
* If you have downloaded a copy of the TencentOS binary from Tencent, please
* note that the TencentOS binary is licensed under the BSD 3-Clause License.
*
* If you have downloaded a copy of the TencentOS source code from Tencent,
* please note that TencentOS source code is licensed under the BSD 3-Clause
* License, except for the third-party components listed below which are
* subject to different license terms. Your integration of TencentOS into your
* own projects may require compliance with the BSD 3-Clause License, as well
* as the other licenses applicable to the third-party components included
* within TencentOS.
*---------------------------------------------------------------------------*/
#include "tos_vfs.h"
extern k_list_t k_vfs_fsmap_list;
TOS_LIST_DEFINE(k_vfs_fsmap_list);
__STATIC__ vfs_fsmap_t *vfs_fsmap_get(const char *fs_name)
{
char *name = K_NULL;
vfs_fsmap_t *fsmap = K_NULL;
TOS_LIST_FOR_EACH_ENTRY(fsmap, vfs_fsmap_t, list, &k_vfs_fsmap_list) {
name = (char *)fsmap->name;
if (strlen(name) == strlen(fs_name) &&
strncmp(name, fs_name, strlen(name)) == 0) {
return fsmap;
}
}
return K_NULL;
}
__STATIC_INLINE__ void vfs_fsmap_set(vfs_fsmap_t *fsmap, const char *fs_name, vfs_fs_ops_t *ops)
{
fsmap->name = fs_name;
fsmap->ops = ops;
tos_list_init(&fsmap->list);
tos_list_add(&fsmap->list, &k_vfs_fsmap_list);
}
__STATIC_INLINE__ void vfs_fsmap_free(vfs_fsmap_t *fsmap)
{
tos_list_del(&fsmap->list);
tos_mmheap_free((void *)fsmap);
}
/*
Actually the "section table hack" is much more cool and elegant, but with that
we must deel with the link script, that will introduce coding complication,
especially develop with IDE. So, linked list with dynamic memory is a compromised
solution here.
*/
__API__ vfs_err_t tos_vfs_fs_register(const char *fs_name, vfs_fs_ops_t *ops)
{
vfs_fsmap_t *fsmap = K_NULL;
if (!fs_name || !ops) {
return VFS_ERR_PARA_INVALID;
}
fsmap = vfs_fsmap_get(fs_name);
if (fsmap) {
return VFS_ERR_FS_ALREADY_REGISTERED;
}
fsmap = (vfs_fsmap_t *)tos_mmheap_calloc(1, sizeof(vfs_fsmap_t));
if (!fsmap) {
return VFS_ERR_OUT_OF_MEMORY;
}
vfs_fsmap_set(fsmap, fs_name, ops);
return VFS_ERR_NONE;
}
__API__ vfs_err_t tos_vfs_fs_unregister(const char *fs_name)
{
vfs_fsmap_t *fsmap = K_NULL;
if (!fs_name) {
return VFS_ERR_PARA_INVALID;
}
fsmap = vfs_fsmap_get(fs_name);
if (!fsmap) {
return VFS_ERR_FS_NOT_REGISTERED;
}
vfs_fsmap_free(fsmap);
return VFS_ERR_NONE;
}
/*
tos_vfs_mount("/dev/block/nand", "/fs/yaffs", "yaffs");
we mount a filesystem named "yaffs" to directory "fs/yaffs", using device "/dev/block/nand"
*/
__API__ vfs_err_t tos_vfs_fs_mount(const char *device_path, const char *dir, const char *fs_name)
{
vfs_fsmap_t *fsmap = K_NULL;
vfs_inode_t *device_inode = K_NULL;
vfs_inode_t *fs_inode = K_NULL;
fsmap = vfs_fsmap_get(fs_name);
if (!fsmap) {
return VFS_ERR_FS_NOT_REGISTERED;
}
device_inode = vfs_inode_find(device_path, K_NULL);
if (!device_inode) {
return VFS_ERR_DEVICE_NOT_REGISTERED;
}
if (!VFS_INODE_IS_DEVICE(device_inode)) {
return VFS_ERR_INODE_INVALID;
}
fs_inode = vfs_inode_find(dir, K_NULL);
if (fs_inode) {
if (VFS_INODE_IS_FILESYSTEM(fs_inode)) {
return VFS_ERR_FS_ALREADY_MOUNTED;
} else {
return VFS_ERR_INODE_INAVALIABLE;
}
}
fs_inode = vfs_inode_alloc(dir);
if (!fs_inode) {
return VFS_ERR_INODE_CREATE_FAILED;
}
VFS_INODE_TYPE_SET(fs_inode, VFS_INODE_TYPE_FILESYSTEM);
fs_inode->ops.fs_ops = fsmap->ops;
if (!fs_inode->ops.fs_ops->bind) {
return VFS_ERR_OPS_NULL;
}
if (fs_inode->ops.fs_ops->bind(fs_inode, device_inode) != 0) {
return VFS_ERR_OPS_FAILED;
}
return VFS_ERR_NONE;
}
__API__ vfs_err_t tos_vfs_fs_umount(const char *dir)
{
vfs_inode_t *inode = K_NULL;
inode = vfs_inode_find(dir, K_NULL);
if (!inode) {
return VFS_ERR_FS_NOT_MOUNT;
}
if (!VFS_INODE_IS_FILESYSTEM(inode)) {
return VFS_ERR_INODE_INAVALIABLE;
}
if (vfs_inode_is_busy(inode)) {
return VFS_ERR_INODE_BUSY;
}
if (!inode->ops.fs_ops->unbind) {
return VFS_ERR_OPS_NULL;
}
if (inode->ops.fs_ops->unbind(inode) != 0) {
return VFS_ERR_OPS_FAILED;
}
return VFS_ERR_NONE;
}
__API__ vfs_err_t tos_vfs_fs_mkfs(const char *device_path, const char *fs_name, int opt, unsigned long arg)
{
vfs_fsmap_t *fsmap = K_NULL;
vfs_inode_t *device_inode = K_NULL;
vfs_inode_t *fs_inode = K_NULL;
fsmap = vfs_fsmap_get(fs_name);
if (!fsmap) {
return VFS_ERR_FS_NOT_REGISTERED;
}
device_inode = vfs_inode_find(device_path, K_NULL);
if (!device_inode) {
return VFS_ERR_DEVICE_NOT_REGISTERED;
}
if (!VFS_INODE_IS_DEVICE(device_inode)) {
return VFS_ERR_INODE_INVALID;
}
fs_inode->ops.fs_ops = fsmap->ops;
if (!fsmap->ops->mkfs) {
return VFS_ERR_OPS_NULL;
}
if (fsmap->ops->mkfs(device_inode, opt, arg) != 0) {
return VFS_ERR_OPS_FAILED;
}
return VFS_ERR_NONE;
}