add OpenHarmony 1.0 baseline
This commit is contained in:
43
fs/fat/Kconfig
Executable file
43
fs/fat/Kconfig
Executable file
@@ -0,0 +1,43 @@
|
||||
config FS_FAT
|
||||
bool "Enable FAT"
|
||||
default y
|
||||
depends on FS_VFS
|
||||
help
|
||||
Answer Y to enable LiteOS support fat filesystem.
|
||||
|
||||
config FS_FAT_CACHE
|
||||
bool "Enable FAT Cache"
|
||||
default y
|
||||
depends on FS_FAT
|
||||
help
|
||||
Answer Y to enable LiteOS fat filesystem support cache.
|
||||
|
||||
config FS_FAT_CACHE_SYNC_THREAD
|
||||
bool "Enable FAT Cache Sync Thread"
|
||||
default n
|
||||
depends on FS_FAT_CACHE
|
||||
help
|
||||
Answer Y to enable LiteOS fat filesystem support cache sync thread.
|
||||
|
||||
config FS_FAT_CHINESE
|
||||
bool "Enable Chinese"
|
||||
default y
|
||||
depends on FS_FAT
|
||||
help
|
||||
Answer Y to enable LiteOS fat filesystem support Chinese.
|
||||
|
||||
config FS_FAT_VIRTUAL_PARTITION
|
||||
bool "Enabel Virtual Partition"
|
||||
default n
|
||||
depends on FS_FAT
|
||||
|
||||
config FS_FAT_VOLUMES
|
||||
int
|
||||
depends on FS_FAT
|
||||
default 32 if PLATFORM_HI3731
|
||||
default 16
|
||||
|
||||
config FS_FAT_DISK
|
||||
bool "Enable partinfo for storage device"
|
||||
depends on FS_FAT || DRIVERS_MMC || DRIVERS_USB
|
||||
default y
|
||||
44
fs/fat/Makefile
Executable file
44
fs/fat/Makefile
Executable file
@@ -0,0 +1,44 @@
|
||||
# Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
# Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
include $(LITEOSTOPDIR)/config.mk
|
||||
|
||||
MODULE_NAME := $(notdir $(shell pwd))
|
||||
|
||||
LOCAL_SRCS := $(wildcard os_adapt/*.c)
|
||||
LOCAL_SRCS += $(wildcard $(LITEOSTHIRDPARTY)/FatFs/source/*.c)
|
||||
|
||||
LOCAL_INCLUDE := \
|
||||
-I $(LITEOSTHIRDPARTY)/FatFs/source \
|
||||
-I $(LITEOSTOPDIR)/fs/fat/virpart/include
|
||||
|
||||
LOCAL_FLAGS := $(LOCAL_INCLUDE) $(LITEOS_GCOV_OPTS)
|
||||
|
||||
include $(MODULE)
|
||||
|
||||
121
fs/fat/os_adapt/fat_shellcmd.c
Executable file
121
fs/fat/os_adapt/fat_shellcmd.c
Executable file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "los_config.h"
|
||||
|
||||
#if defined(LOSCFG_SHELL) && defined(LOSCFG_FS_FAT)
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include "shcmd.h"
|
||||
#include "shell.h"
|
||||
#include "fs/fs.h"
|
||||
#include "fatfs.h"
|
||||
|
||||
int osShellCmdFormat(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3) { /* 3, at least 3 params for this shell command. */
|
||||
perror("format error");
|
||||
PRINTK("Usage :\n");
|
||||
PRINTK(" format <dev_inodename> <sectors> <option> <label>\n");
|
||||
PRINTK(" dev_inodename : the name of dev\n");
|
||||
PRINTK(" sectors : Size of allocation unit in unit of byte or sector, ");
|
||||
PRINTK("0 instead of default size\n");
|
||||
PRINTK(" options : Index of filesystem. 1 for FAT filesystem, ");
|
||||
PRINTK("2 for FAT32 filesystem, 7 for any, 8 for erase\n");
|
||||
PRINTK(" label : The volume of device. It will be emptyed when this parameter is null\n");
|
||||
PRINTK("Example:\n");
|
||||
PRINTK(" format /dev/mmcblk0 128 2\n");
|
||||
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 4) { /* 4, if the params count is equal to 4, then do this. */
|
||||
/* 3, get the param and check. */
|
||||
if (strncmp(argv[3], "NULL", strlen(argv[3])) == 0 || strncmp(argv[3], "null", strlen(argv[3])) == 0) {
|
||||
set_label(NULL);
|
||||
} else {
|
||||
set_label(argv[3]);
|
||||
}
|
||||
}
|
||||
/* 0, 1, 2, get the param and check it. */
|
||||
if (format(argv[0], atoi(argv[1]), atoi(argv[2])) == 0) {
|
||||
PRINTK("format %s Success \n", argv[0]);
|
||||
} else {
|
||||
perror("format error");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
int osShellCmdVirstatfs(int argc, char** argv)
|
||||
{
|
||||
struct statfs sfs;
|
||||
unsigned long long totalSize, freeSize;
|
||||
int result;
|
||||
(void)memset_s(&sfs, sizeof(sfs), 0, sizeof(sfs));
|
||||
if (argc != 1) {
|
||||
perror("virstatfs error");
|
||||
PRINTK("Usage :\n");
|
||||
PRINTK(" virstatfs <virtual_entry>\n");
|
||||
PRINTK(" virtual_entry : the path of the virtual partition entry\n");
|
||||
PRINTK("Example:\n");
|
||||
PRINTK(" virstatfs /mnt/sd/virpart0\n");
|
||||
return FAT_ERROR;
|
||||
}
|
||||
|
||||
result = virstatfs(argv[0], &sfs);
|
||||
if (result < 0) {
|
||||
set_errno(-result);
|
||||
perror("virstatfs failed");
|
||||
return FAT_ERROR;
|
||||
}
|
||||
totalSize = (unsigned long long)sfs.f_bsize * sfs.f_blocks;
|
||||
freeSize = (unsigned long long)sfs.f_bsize * sfs.f_bfree;
|
||||
|
||||
PRINTK("Virtual partition \"%s\" Info:\n", argv[0]);
|
||||
PRINTK(" f_type = %d\n cluster_size = %d\n total_clusters = 0x%llx\n ",
|
||||
sfs.f_type, sfs.f_bsize, sfs.f_blocks);
|
||||
PRINTK("free_clusters = 0x%llx\n avail_clusters = 0x%llx\n f_namelen = %d\n",
|
||||
sfs.f_bfree, sfs.f_bavail, sfs.f_namelen);
|
||||
PRINTK("\n%s\n total size: %4llu Bytes\n free size: %4llu Bytes\n", argv[0], totalSize, freeSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LOSCFG_FS_FAT_VIRTUAL_PARTITION) && defined(LOSCFG_SHELL_CMD_DEBUG)
|
||||
SHELLCMD_ENTRY(virstatfs_shellcmd, CMD_TYPE_EX, "virstatfs", XARGS, (CmdCallBackFunc)osShellCmdVirstatfs);
|
||||
#endif
|
||||
SHELLCMD_ENTRY(format_shellcmd, CMD_TYPE_EX, "format", XARGS, (CmdCallBackFunc)osShellCmdFormat);
|
||||
#endif
|
||||
2419
fs/fat/os_adapt/fatfs.c
Executable file
2419
fs/fat/os_adapt/fatfs.c
Executable file
File diff suppressed because it is too large
Load Diff
41
fs/fat/virpart/Makefile
Executable file
41
fs/fat/virpart/Makefile
Executable file
@@ -0,0 +1,41 @@
|
||||
# Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
# Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software without specific prior written
|
||||
# permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
include $(LITEOSTOPDIR)/config.mk
|
||||
|
||||
MODULE_NAME := $(notdir $(shell pwd))
|
||||
|
||||
LOCAL_SRCS := $(wildcard src/*.c)
|
||||
|
||||
LOCAL_INCLUDE := \
|
||||
-I $(LITEOSTOPDIR)/fs/fat/virpart/include
|
||||
|
||||
LOCAL_FLAGS := $(LOCAL_INCLUDE) $(LITEOS_GCOV_OPTS)
|
||||
|
||||
include $(MODULE)
|
||||
46
fs/fat/virpart/include/virpart.h
Executable file
46
fs/fat/virpart/include/virpart.h
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _VIRPART_H
|
||||
#define _VIRPART_H
|
||||
|
||||
#include "ff.h"
|
||||
#include "disk.h"
|
||||
|
||||
extern char g_devPartName[DISK_NAME + 1];
|
||||
|
||||
INT FatFsBindVirPart(void *handle, BYTE vol);
|
||||
|
||||
INT FatFsUnbindVirPart(void *handle);
|
||||
|
||||
INT FatFsMakeVirPart(void *handle, BYTE vol);
|
||||
|
||||
#endif /* _VIRPART_H */
|
||||
54
fs/fat/virpart/include/virpartff.h
Executable file
54
fs/fat/virpart/include/virpartff.h
Executable file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _VIRPARTFF_H
|
||||
#define _VIRPARTFF_H
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
|
||||
extern FAT_VIR_PART g_fatVirPart;
|
||||
|
||||
FRESULT follow_virentry(FFOBJID *obj, const TCHAR *path);
|
||||
FATFS* f_getfatfs(int vol);
|
||||
FRESULT f_checkname(const TCHAR *path);
|
||||
FRESULT f_boundary(FATFS *fs, DWORD clust);
|
||||
FRESULT f_disvirfs(FATFS *fs);
|
||||
FRESULT f_unregvirfs(FATFS *fs);
|
||||
FRESULT f_regvirfs(FATFS *fs);
|
||||
FRESULT f_scanfat(FATFS *fs);
|
||||
FRESULT f_checkvirpart(FATFS *fs, const TCHAR *path, BYTE vol);
|
||||
FRESULT f_makevirpart(FATFS *fs, const TCHAR *path, BYTE vol);
|
||||
FRESULT f_getvirfree(const TCHAR *path, DWORD *nclst, DWORD *cclst);
|
||||
|
||||
#endif
|
||||
#endif /* _VIRPARTFF_H */
|
||||
503
fs/fat/virpart/src/virpart.c
Executable file
503
fs/fat/virpart/src/virpart.c
Executable file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "virpart.h"
|
||||
#include "errno.h"
|
||||
#include "fatfs.h"
|
||||
#include "dirop_fat.h"
|
||||
#include "errcode_fat.h"
|
||||
#include "disk.h"
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_CACHE
|
||||
#include "bcache.h"
|
||||
#endif
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
|
||||
#include "virpartff.h"
|
||||
|
||||
char g_devPartName[DISK_NAME + 1] = {0};
|
||||
|
||||
static INT FatFsCheckPercent(virpartinfo *virtualinfo)
|
||||
{
|
||||
double virtPercent = 0.0;
|
||||
INT partCount;
|
||||
|
||||
for (partCount = 0; partCount < virtualinfo->virpartnum; partCount++) {
|
||||
if (virtualinfo->virpartpercent[partCount] <= _FLOAT_ACC ||
|
||||
virtualinfo->virpartpercent[partCount] >= (1 - _FLOAT_ACC)) {
|
||||
set_errno(VIRERR_PARMPERCENTERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
virtPercent += virtualinfo->virpartpercent[partCount];
|
||||
}
|
||||
|
||||
if (virtPercent >= (1 + _FLOAT_ACC)) {
|
||||
set_errno(VIRERR_PARMPERCENTERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT FatFsCheckName(virpartinfo *virtualinfo)
|
||||
{
|
||||
INT partCount, loopCount, len;
|
||||
FRESULT res;
|
||||
|
||||
for (partCount = 0; partCount < virtualinfo->virpartnum; partCount++) {
|
||||
len = ff_strnlen(virtualinfo->virpartname[partCount], _MAX_ENTRYLENGTH + 1);
|
||||
if (len <= 0 || len > _MAX_ENTRYLENGTH) {
|
||||
set_errno(VIRERR_PARMNAMEERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = f_checkname(virtualinfo->virpartname[partCount]);
|
||||
if (res != FR_OK) {
|
||||
set_errno(VIRERR_PARMNAMEERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (partCount = 0; partCount < virtualinfo->virpartnum; partCount++) {
|
||||
for (loopCount = partCount + 1; loopCount < virtualinfo->virpartnum; loopCount++) {
|
||||
if ((memcmp(virtualinfo->virpartname[partCount], virtualinfo->virpartname[loopCount],
|
||||
_MAX_ENTRYLENGTH)) == 0) {
|
||||
set_errno(VIRERR_PARMNAMEERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT los_set_virpartparam(virpartinfo virtualinfo)
|
||||
{
|
||||
INT ret;
|
||||
UINT minSize;
|
||||
UINT dstNameSize;
|
||||
char devHead[DISK_NAME + 1] = "/dev/";
|
||||
|
||||
g_fatVirPart.virtualinfo.devpartpath = g_devPartName;
|
||||
|
||||
if (g_fatVirPart.isparamset == TRUE) {
|
||||
set_errno(VIRERR_PARMLOCKED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_fatVirPart.isparamset = TRUE;
|
||||
|
||||
if (virtualinfo.virpartnum < 1 || virtualinfo.virpartnum > _MAX_VIRVOLUMES) {
|
||||
set_errno(VIRERR_PARMNUMERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = FatFsCheckPercent(&virtualinfo);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = FatFsCheckName(&virtualinfo);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strlen(virtualinfo.devpartpath) <= strlen(devHead)) {
|
||||
set_errno(VIRERR_PARMDEVERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(virtualinfo.devpartpath, devHead, strlen(devHead)) != 0) {
|
||||
set_errno(VIRERR_PARMDEVERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dstNameSize = sizeof(g_devPartName);
|
||||
minSize = dstNameSize < strlen(virtualinfo.devpartpath) ? dstNameSize : strlen(virtualinfo.devpartpath);
|
||||
ret = strncpy_s(g_fatVirPart.virtualinfo.devpartpath, dstNameSize, virtualinfo.devpartpath, minSize);
|
||||
if (ret != EOK) {
|
||||
set_errno(VIRERR_PARMNAMEERR);
|
||||
g_fatVirPart.isparamset = FALSE;
|
||||
return -1;
|
||||
}
|
||||
g_fatVirPart.virtualinfo.devpartpath[dstNameSize - 1] = '\0';
|
||||
|
||||
(void)memcpy_s(g_fatVirPart.virtualinfo.virpartname, sizeof(g_fatVirPart.virtualinfo.virpartname),
|
||||
virtualinfo.virpartname, sizeof(virtualinfo.virpartname));
|
||||
(void)memcpy_s(g_fatVirPart.virtualinfo.virpartpercent, sizeof(g_fatVirPart.virtualinfo.virpartpercent),
|
||||
virtualinfo.virpartpercent, sizeof(virtualinfo.virpartpercent));
|
||||
g_fatVirPart.virtualinfo.virpartnum = virtualinfo.virpartnum;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT FatfsDisablePart(void *handle)
|
||||
{
|
||||
FATFS *fs = (FATFS *)handle;
|
||||
return fatfs_2_vfs(f_disvirfs(fs));
|
||||
}
|
||||
|
||||
/*
|
||||
* FatfsScanFat:
|
||||
* Scan the FAT inside the boundary of CHILD FATFS limit, and update the free cluster and last cluster
|
||||
* for all CHILD FATFS.
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Successfully scaned the FAT and update field.
|
||||
* Others Return Value:
|
||||
* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
|
||||
* - FR_DENIED : The virtual partition feature has been shut down by switcher
|
||||
* - FR_DISK_ERR : A disk error happened
|
||||
*/
|
||||
static INT FatfsScanFat(void *handle)
|
||||
{
|
||||
FATFS *fat = (FATFS *)handle;
|
||||
UINT i;
|
||||
INT ret;
|
||||
|
||||
for (i = 0; i < fat->vir_amount; i++) {
|
||||
/* Assert error will not abort the scanning process */
|
||||
ret = f_scanfat(CHILDFS(fat, i));
|
||||
if (ret != FR_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* FatfsScanClear:
|
||||
* Scan the root directory clean completely, regardless of the virtual partition entry.
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : The root directory is completely clean.
|
||||
* - FR_NOTCLEAR : The root dircotory is not clean.
|
||||
* Others Return Value:
|
||||
* Followed the by the lower API.
|
||||
*/
|
||||
static FRESULT FatfsScanClear(INT vol)
|
||||
{
|
||||
FRESULT ret;
|
||||
DIR dir;
|
||||
FILINFO fno;
|
||||
CHAR path[MAX_LFNAME_LENTH];
|
||||
INT num;
|
||||
INT res;
|
||||
|
||||
/* num : for the amount of all item in root directory */
|
||||
num = 0;
|
||||
|
||||
(void)memset_s(path, sizeof(path), 0, sizeof(path));
|
||||
|
||||
res = snprintf_s(path, MAX_LFNAME_LENTH, MAX_LFNAME_LENTH - 1, "%d:/", vol);
|
||||
if (res < 0) {
|
||||
return FR_INVALID_NAME;
|
||||
}
|
||||
|
||||
ret = f_opendir(&dir, path);
|
||||
if (ret != FR_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Scan all entry for searching virtual partition directory and others in root directory */
|
||||
while (1) {
|
||||
(void)memset_s(&fno, sizeof(FILINFO), 0, sizeof(FILINFO));
|
||||
ret = f_readdir(&dir, &fno);
|
||||
/* Reach the end of directory, or the root direcotry is empty, abort the scanning operation */
|
||||
if (fno.fname[0] == 0x00 || fno.fname[0] == (TCHAR)0xFF) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != FR_OK) {
|
||||
(void)f_closedir(&dir);
|
||||
return ret;
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
/* Close the directory */
|
||||
ret = f_closedir(&dir);
|
||||
if ((ret == FR_OK) && (num != 0)) {
|
||||
return FR_NOTCLEAR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* FatfsBuildEntry:
|
||||
* Scan virtual partition entry in root directory, and try to rebuild the
|
||||
* error virtual partition, according to the scanning result.
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : The root directory is completely clean.
|
||||
* - FR_OCCUPIED : The virtual partition entry has been occupied by the same name file.
|
||||
* - FR_CHAIN_ERR : The virtual partition entry has been rebuilt along the invaild cluster
|
||||
* chain.
|
||||
* Others Return Value:
|
||||
* Followed the by the lower API
|
||||
*/
|
||||
static FRESULT FatfsBuildEntry(FATFS *fat, INT vol)
|
||||
{
|
||||
UINT i;
|
||||
CHAR path[MAX_LFNAME_LENTH];
|
||||
FRESULT ret;
|
||||
DIR dir;
|
||||
INT res;
|
||||
|
||||
for (i = 0; i < fat->vir_amount; i++) {
|
||||
res = snprintf_s(path, MAX_LFNAME_LENTH, MAX_LFNAME_LENTH - 1, "%d:%s", vol, CHILDFS(fat, i)->namelabel);
|
||||
if (res < 0) {
|
||||
return FR_INVALID_NAME;
|
||||
}
|
||||
|
||||
ret = f_mkdir(path);
|
||||
if (ret == FR_EXIST) {
|
||||
(void)memset_s(&dir, sizeof(dir), 0, sizeof(dir));
|
||||
ret = f_opendir(&dir, path);
|
||||
if (ret == FR_NO_DIR) {
|
||||
return FR_OCCUPIED;
|
||||
}
|
||||
if (ret == FR_OK) {
|
||||
ret = f_boundary(CHILDFS(fat, i), dir.obj.sclust);
|
||||
if (ret != FR_OK) {
|
||||
(void)f_closedir(&dir);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
ret = f_closedir(&dir);
|
||||
if (ret != FR_OK) {
|
||||
return ret;
|
||||
}
|
||||
} else if (ret != FR_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* FatFsUnbindVirPart:
|
||||
* Uninitialized the CHILD FATFS object
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - ENOERR : Successfully initialized the CHILD FATFS object.
|
||||
*/
|
||||
INT FatFsUnbindVirPart(void *handle)
|
||||
{
|
||||
INT ret;
|
||||
FATFS *fat = (FATFS *)handle;
|
||||
ret = f_unregvirfs(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* FatFsBindVirPart:
|
||||
* Bind the virtual partition
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Finished the virtual partition.
|
||||
* The virtual partition result can refer by API
|
||||
*/
|
||||
INT FatFsBindVirPart(void *handle, BYTE vol)
|
||||
{
|
||||
INT ret;
|
||||
FATFS *fat = (FATFS *)handle;
|
||||
char path[MAX_LFNAME_LENTH] = {0};
|
||||
|
||||
if (fat == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%d:/", vol);
|
||||
if (ret < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Detect the information in the reserve sector and try to set virtual partition by sector info */
|
||||
ret = f_checkvirpart(fat, path, vol);
|
||||
if (ret == FR_NOVIRPART) {
|
||||
/* Failed to use the External SD setting, try to use the current setting to external SD and rebuild entries */
|
||||
/* Check the enviorment whether it is fit for virtual parition */
|
||||
ret = FatfsScanClear(vol);
|
||||
if (ret != FR_OK) {
|
||||
/* A error happened in the file operation */
|
||||
(void)FatfsDisablePart(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
/* Ready to fit the SD card to virtual partition featrue */
|
||||
ret = f_makevirpart(fat, path, vol);
|
||||
if (ret != FR_OK) {
|
||||
(void)FatfsDisablePart(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
} else if (ret != FR_OK) {
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
/* Try to build the virtual entry */
|
||||
ret = FatfsBuildEntry(fat, vol);
|
||||
if (ret != FR_OK) {
|
||||
(void)FatfsDisablePart(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
#ifdef LOSCFG_FS_FAT_CACHE
|
||||
los_part *part = NULL;
|
||||
if (ret == FR_OK) {
|
||||
part = get_part((int)fat->pdrv);
|
||||
if (part != NULL) {
|
||||
ret = OsSdSync(part->disk_id);
|
||||
if (ret < 0) {
|
||||
ret = -EIO;
|
||||
}
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ret == FR_OK) {
|
||||
ret = FatfsScanFat(fat);
|
||||
if (ret != FR_OK) {
|
||||
(void)FatfsDisablePart(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
}
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* FatFsMakeVirPart:
|
||||
* Bind the virtual partition
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Finished the virtual partition.
|
||||
* The virtual partition result can refer by API
|
||||
*/
|
||||
INT FatFsMakeVirPart(void *handle, BYTE vol)
|
||||
{
|
||||
INT ret;
|
||||
FATFS *fat = (FATFS *)handle;
|
||||
char path[MAX_LFNAME_LENTH] = {0};
|
||||
|
||||
if (fat == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%d:/", vol);
|
||||
if (ret < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Ready to fit the SD card to virtual partition featrue */
|
||||
ret = f_makevirpart(fat, path, vol);
|
||||
if (ret != FR_OK) {
|
||||
(void)FatfsDisablePart(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
|
||||
/* Try to build the virtual entry */
|
||||
ret = FatfsBuildEntry(fat, vol);
|
||||
if (ret != FR_OK) {
|
||||
(void)FatfsDisablePart(fat);
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
|
||||
return fatfs_2_vfs(ret);
|
||||
}
|
||||
|
||||
INT fatfs_virstatfs_internel(struct inode *mountpt, const char *relpath, struct statfs *buf)
|
||||
{
|
||||
char drive[MAX_LFNAME_LENTH];
|
||||
DWORD freClust, allClust;
|
||||
FATFS *fat = NULL;
|
||||
INT result, vol;
|
||||
|
||||
fat = (FATFS *)mountpt->i_private;
|
||||
FAT_CHECK(fat);
|
||||
|
||||
if (fat->vir_flag != FS_PARENT) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vol = fatfs_get_vol(fat);
|
||||
if (vol < 0 || vol > FF_VOLUMES) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (strlen(relpath) > MAX_LFNAME_LENTH) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
result = snprintf_s(drive, sizeof(drive), sizeof(drive) - 1, "%d:%s", vol, relpath);
|
||||
if (result < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
result = f_getvirfree(drive, &freClust, &allClust);
|
||||
if (result != FR_OK) {
|
||||
result = fatfs_2_vfs(result);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
(void)memset_s((void *)buf, sizeof(struct statfs), 0, sizeof(struct statfs));
|
||||
buf->f_type = MSDOS_SUPER_MAGIC;
|
||||
buf->f_bfree = freClust;
|
||||
buf->f_bavail = freClust;
|
||||
buf->f_blocks = allClust;
|
||||
#if FF_MAX_SS != FF_MIN_SS
|
||||
buf->f_bsize = fat->ssize * fat->csize;
|
||||
#else
|
||||
buf->f_bsize = FF_MIN_SS * fat->csize;
|
||||
#endif
|
||||
#if FF_USE_LFN
|
||||
buf->f_namelen = FF_MAX_LFN; /* Maximum length of filenames */
|
||||
#else
|
||||
/*
|
||||
* Maximum length of filenames,'8' is the effective length, '1' is the terminator,
|
||||
* and '3' is the special length
|
||||
*/
|
||||
buf->f_namelen = (8 + 1 + 3);
|
||||
#endif
|
||||
|
||||
EXIT:
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
872
fs/fat/virpart/src/virpartff.c
Executable file
872
fs/fat/virpart/src/virpartff.c
Executable file
@@ -0,0 +1,872 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ffconf.h"
|
||||
#include "virpartff.h"
|
||||
#include "string.h"
|
||||
#include "diskio.h"
|
||||
|
||||
#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
|
||||
|
||||
#if FF_USE_LFN == 0 /* Non-LFN configuration */
|
||||
#define DEF_NAMBUF
|
||||
#define INIT_NAMBUF(fs)
|
||||
#define FREE_NAMBUF()
|
||||
|
||||
#else /* LFN configuration */
|
||||
#if (FF_MAX_LFN < 12) || (FF_MAX_LFN > 255)
|
||||
#error Wrong _MAX_LFN value
|
||||
#endif
|
||||
|
||||
#if FF_USE_LFN == 1 /* LFN enabled with static working buffer */
|
||||
static WCHAR g_lfnBuf[FF_MAX_LFN + 1]; /* LFN enabled with static working buffer */
|
||||
#define DEF_NAMBUF
|
||||
#define INIT_NAMBUF(fs)
|
||||
#define FREE_NAMBUF()
|
||||
|
||||
#elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */
|
||||
#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN + 1];
|
||||
#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; }
|
||||
#define FREE_NAMBUF()
|
||||
|
||||
#elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */
|
||||
#define DEF_NAMBUF WCHAR *lfn;
|
||||
#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN + 1) * 2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; }
|
||||
#define FREE_NAMBUF() ff_memfree(lfn)
|
||||
|
||||
#else
|
||||
#error Wrong FF_USE_LFN setting
|
||||
|
||||
#endif
|
||||
#endif /* else FF_USE_LFN == 0 */
|
||||
|
||||
|
||||
#if FF_FS_REENTRANT
|
||||
#if FF_USE_LFN == 1
|
||||
#error Static LFN work area cannot be used at thread-safe configuration
|
||||
#endif
|
||||
#define ENTER_FF(fs) do { if (!lock_fs(fs)) return FR_TIMEOUT; } while (0)
|
||||
#define LEAVE_FF(fs, res) do { unlock_fs(fs, res); return res; } while (0)
|
||||
#else
|
||||
#define ENTER_FF(fs)
|
||||
#define LEAVE_FF(fs, res) return (res)
|
||||
#endif
|
||||
|
||||
extern FATFS *FatFs[FF_VOLUMES];
|
||||
|
||||
/*
|
||||
* follow_virentry:
|
||||
* Compare the top segment with the virtual partition entry and replace it to its CHILD FATFS
|
||||
*
|
||||
* Acceptable return vaule:
|
||||
* - FR_OK : The top segment matches one of the virtual partition entries, and the FATFS
|
||||
* has been replaced to the corresponding FATFS.
|
||||
* - FR_DENIED : The top segment does not matched any of the virtual partition entries, and
|
||||
* the FATFS has kept as it is. Or the virtual partition feature has been
|
||||
* switched down by any reason.
|
||||
* - FR_INT_ERR : Assertion error
|
||||
*/
|
||||
FRESULT follow_virentry(FFOBJID *obj, const TCHAR *path)
|
||||
{
|
||||
TCHAR keyword[FF_MAX_LFN + 1] = {0};
|
||||
FATFS *fs = obj->fs;
|
||||
INT len;
|
||||
UINT i;
|
||||
|
||||
(void)memset_s(keyword, sizeof(keyword), 0, sizeof(keyword));
|
||||
/* Search and copy the first segment in path */
|
||||
for (len = 0; *path != '/' && *path != '\\' && *path != '\0' && len < FF_MAX_LFN; path++, len++) {
|
||||
keyword[len] = *path;
|
||||
}
|
||||
|
||||
if (len == 0 || len > _MAX_ENTRYLENGTH) {
|
||||
return FR_DENIED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the segment does match one for virtual partitions' entry or not,
|
||||
* replace the FATFS if the result is positive
|
||||
*/
|
||||
for (i = 0; i < fs->vir_amount; i++) {
|
||||
if (!CHILDFS(fs, i)) {
|
||||
return FR_INT_ERR;
|
||||
}
|
||||
if (memcmp((CHILDFS(fs, i))->namelabel, keyword, _MAX_ENTRYLENGTH + 1) == 0) {
|
||||
obj->fs = CHILDFS(fs, i);
|
||||
return FR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return FR_DENIED;
|
||||
}
|
||||
|
||||
FRESULT f_checkname(const TCHAR *path)
|
||||
{
|
||||
FRESULT res;
|
||||
DIR dj;
|
||||
FATFS fs;
|
||||
TCHAR *label = (TCHAR *)path;
|
||||
DEF_NAMBUF
|
||||
|
||||
(void)memset_s(&fs, sizeof(fs), 0, sizeof(fs));
|
||||
dj.obj.fs = &fs;
|
||||
INIT_NAMBUF(&fs);
|
||||
res = create_name(&dj, &path);
|
||||
/* the last byte of file name can't be a space */
|
||||
if (res == FR_OK && dj.fn[11] == 0x20) {
|
||||
res = FR_INVALID_NAME;
|
||||
return res;
|
||||
}
|
||||
|
||||
FREE_NAMBUF();
|
||||
|
||||
for (; *label != '\0'; label++) {
|
||||
if (label - path > _MAX_ENTRYLENGTH) {
|
||||
res = FR_INVALID_NAME;
|
||||
return res;
|
||||
}
|
||||
if (*label == '/' || *label == '\\') {
|
||||
res = FR_INVALID_NAME;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
FATFS *f_getfatfs(int vol)
|
||||
{
|
||||
FATFS *fs = NULL;
|
||||
if (vol < 0 || vol >= FF_VOLUMES) {
|
||||
fs = NULL;
|
||||
} else {
|
||||
fs = FatFs[vol];
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
static FRESULT FatfsCheckBoundParam(FATFS *fs, DWORD clust)
|
||||
{
|
||||
if (fs->st_clst <= 2 || (fs->st_clst + fs->ct_clst) > fs->n_fatent) {
|
||||
return FR_INT_ERR;
|
||||
}
|
||||
if (clust < 2 || clust > fs->n_fatent) {
|
||||
return FR_INT_ERR;
|
||||
}
|
||||
if (clust >= (fs->st_clst + fs->ct_clst) || clust < fs->st_clst) {
|
||||
return FR_CHAIN_ERR;
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* check_boundary:
|
||||
* Check the chain occupied more than one virtual partition or not start at the var 'clust'
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : The chain occupied only one virtual parition
|
||||
* - FR_CHAIN_ERR : The chain occupied more than one virtual parition
|
||||
*/
|
||||
FRESULT f_boundary(FATFS *fs, DWORD clust)
|
||||
{
|
||||
FFOBJID obj;
|
||||
FRESULT res;
|
||||
obj.fs = fs;
|
||||
if (fs == NULL) {
|
||||
return FR_INT_ERR;
|
||||
}
|
||||
if (fs->fs_type != FS_FAT32) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
ENTER_FF(fs);
|
||||
|
||||
res = FatfsCheckBoundParam(fs, clust);
|
||||
if (res != FR_OK) {
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
for (; ;) {
|
||||
clust = get_fat(&obj, clust);
|
||||
if (clust == 0xFFFFFFFF) {
|
||||
LEAVE_FF(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (clust == 0x0FFFFFFF) {
|
||||
break;
|
||||
}
|
||||
if (clust < 2 || clust >= fs->n_fatent) {
|
||||
LEAVE_FF(fs, FR_INT_ERR);
|
||||
}
|
||||
if (clust >= (fs->st_clst + fs->ct_clst) || clust < fs->st_clst) {
|
||||
LEAVE_FF(fs, FR_CHAIN_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
LEAVE_FF(fs, FR_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* f_unregvirfs:
|
||||
* Uninitialized the CHILD FATFS object
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Successfully initialized the CHILD FATFS object.
|
||||
*/
|
||||
FRESULT f_disvirfs(FATFS *fs)
|
||||
{
|
||||
if (ISCHILD(fs)) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
if (fs->vir_amount > _MAX_VIRVOLUMES) {
|
||||
return FR_INT_ERR;
|
||||
}
|
||||
|
||||
ENTER_FF(fs);
|
||||
|
||||
(void)f_unregvirfs(fs);
|
||||
LEAVE_FF(fs, FR_OK);
|
||||
}
|
||||
|
||||
FRESULT f_unregvirfs(FATFS *fs)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (fs == NULL || ISCHILD(fs)) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
fs->vir_avail = FS_VIRDISABLE;
|
||||
/* PARENT FATFS has linked to CHILD FATFS already */
|
||||
if (fs->child_fs != NULL) {
|
||||
/* Followed the CHILD FATFS and free the memory */
|
||||
for (i = 0; i < fs->vir_amount; i++) {
|
||||
if (CHILDFS(fs, i) != NULL) {
|
||||
ff_memfree(CHILDFS(fs, i));
|
||||
}
|
||||
}
|
||||
/* Free the 'child_fs' feild */
|
||||
ff_memfree(fs->child_fs);
|
||||
fs->child_fs = NULL;
|
||||
fs->vir_amount = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
static void FatfsSetParentFs(FATFS *pfs, FATFS *fs)
|
||||
{
|
||||
pfs->fs_type = fs->fs_type; /* Copy the feild info from PARENT FATFS object */
|
||||
pfs->pdrv = fs->pdrv;
|
||||
pfs->n_fats = fs->n_fats;
|
||||
pfs->id = fs->id;
|
||||
pfs->n_rootdir = fs->n_rootdir;
|
||||
pfs->csize = fs->csize;
|
||||
#if FF_MAX_SS != FF_MIN_SS
|
||||
pfs->ssize = fs->ssize;
|
||||
#endif
|
||||
pfs->sobj = fs->sobj;
|
||||
|
||||
#if FF_FS_RPATH != 0
|
||||
pfs->cdir = 0;
|
||||
#endif
|
||||
pfs->n_fatent = fs->n_fatent;
|
||||
pfs->fsize = fs->fsize;
|
||||
pfs->volbase = fs->volbase;
|
||||
pfs->fatbase = fs->fatbase;
|
||||
pfs->dirbase = fs->dirbase;
|
||||
pfs->database = fs->database;
|
||||
pfs->last_clst = 0xFFFFFFFF; /* Mark the 'last_clst' and 'free_clst' in CHILD FATFS is not been updated for now */
|
||||
pfs->free_clst = 0xFFFFFFFF;
|
||||
pfs->st_clst = 0xFFFFFFFF; /* Mark the 'st_clst' and 'ct_clst' in CHILD FATFS is not been update for now. */
|
||||
pfs->ct_clst = 0xFFFFFFFF;
|
||||
pfs->vir_flag = FS_CHILD; /* Mark the FATFS object is a CHILD */
|
||||
pfs->vir_avail = FS_VIRENABLE; /* Mark the CHILD object is enable for now */
|
||||
pfs->parent_fs = (void *)fs; /* Link to the PARENT object */
|
||||
pfs->child_fs = (void *)NULL; /* Link the unrelated feild to NULL */
|
||||
}
|
||||
|
||||
/*
|
||||
* f_regvirfs:
|
||||
* Initialized the CHILD FATFS object
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Successfully initialized the CHILD FATFS object.
|
||||
*
|
||||
* Others Return Value:
|
||||
* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
|
||||
* - FR_DENIED : The virtual partition feature has been shut down by switcher
|
||||
* - FR_DISK_ERR : A disk error happened
|
||||
* - FR_NOT_ENOUGH_CORE : Not enough memory for allocate space for CHILD FATFS
|
||||
* - FR_INVALID_PARAMETER : There is a invaild value in current setting
|
||||
*/
|
||||
FRESULT f_regvirfs(FATFS *fs)
|
||||
{
|
||||
UINT i;
|
||||
FATFS *pfs = NULL;
|
||||
|
||||
if (fs == NULL || ISCHILD(fs)) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
if (fs->vir_amount > _MAX_VIRVOLUMES) {
|
||||
return FR_INT_ERR;
|
||||
}
|
||||
|
||||
fs->parent_fs = (void *)fs; /* Relink to itself */
|
||||
/* Mark the FATFS object is PARENT */
|
||||
fs->st_clst = 0xFFFFFFFF;
|
||||
fs->ct_clst = 0xFFFFFFFF;
|
||||
/* Allocate a space for linking to the child FATFS */
|
||||
fs->child_fs = (void **)ff_memalloc(fs->vir_amount * sizeof(void *));
|
||||
if (fs->child_fs == NULL) {
|
||||
return FR_NOT_ENOUGH_CORE;
|
||||
}
|
||||
fs->vir_avail = FS_VIRENABLE; /* Mark the PARENT object is enable for now */
|
||||
|
||||
/* Set the CHILD object field */
|
||||
for (i = 0; i < fs->vir_amount; i++) {
|
||||
pfs = ff_memalloc(sizeof(FATFS)); /* Allocate a memeory for current child FATFS object */
|
||||
if (pfs == NULL) { /* If allocate failed, must call 'f_unregvirfs' to free the previous FATFS object memory */
|
||||
goto ERROUT;
|
||||
}
|
||||
FatfsSetParentFs(pfs, fs);
|
||||
*(fs->child_fs + i) = (void *)pfs;
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
ERROUT:
|
||||
while (i > 0) {
|
||||
--i;
|
||||
ff_memfree(*(fs->child_fs + i));
|
||||
}
|
||||
ff_memfree(fs->child_fs);
|
||||
fs->child_fs = NULL;
|
||||
|
||||
return FR_NOT_ENOUGH_CORE;
|
||||
}
|
||||
|
||||
static FRESULT FatfsCheckScanFatParam(FATFS *fs)
|
||||
{
|
||||
if (fs == NULL) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
if (ISNORMAL(fs)) {
|
||||
return FR_DENIED;
|
||||
}
|
||||
|
||||
if (fs->fs_type != FS_FAT32 || ISPARENT(fs)) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
if (fs->st_clst < 3 || fs->st_clst >= fs->n_fatent) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
if (fs->ct_clst == 0 || fs->ct_clst > (fs->n_fatent - 3)) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
if ((fs->st_clst + fs->ct_clst) > fs->n_fatent || (fs->st_clst + fs->ct_clst) < 3) {
|
||||
return FR_INVAILD_FATFS;
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* f_scanfat:
|
||||
* Scan the FAT inside the boundary of CHILD FATFS limit, and update the free cluster and last cluster
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Successfully scaned the FAT and update field.
|
||||
*
|
||||
* Others Return Value:
|
||||
* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
|
||||
* - FR_DENIED : The virtual partition feature has been shut down by switcher
|
||||
* - FR_DISK_ERR : A disk error happened
|
||||
*/
|
||||
FRESULT f_scanfat(FATFS *fs)
|
||||
{
|
||||
FRESULT res;
|
||||
DWORD clst;
|
||||
DWORD link;
|
||||
FFOBJID obj;
|
||||
|
||||
res = FatfsCheckScanFatParam(fs);
|
||||
if (res != FR_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ENTER_FF(fs);
|
||||
res = FR_OK;
|
||||
obj.fs = fs;
|
||||
|
||||
fs->free_clst = fs->ct_clst;
|
||||
for (clst = fs->st_clst; clst < fs->st_clst + fs->ct_clst; clst++) {
|
||||
link = get_fat(&obj, clst);
|
||||
if (link == 0xFFFFFFFF) {
|
||||
LEAVE_FF(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (link == 0) {
|
||||
continue;
|
||||
}
|
||||
fs->free_clst--;
|
||||
}
|
||||
fs->last_clst = fs->st_clst - 1;
|
||||
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
static FRESULT FatfsCheckStart(BYTE *work, FATFS *fs, BYTE vol)
|
||||
{
|
||||
DWORD startBaseSect, countBaseSect;
|
||||
|
||||
countBaseSect = LD2PC(vol); /* Volume Base Sectors Count */
|
||||
startBaseSect = LD2PS(vol); /* Volume Base Start Sector */
|
||||
|
||||
/* Check ASCII for Keyword "LITE" */
|
||||
if (ld_dword(work + VR_VertifyString) != 0x4C495445) {
|
||||
return FR_NOVIRPART;
|
||||
}
|
||||
/* Check whether filesystem has been changed or not */
|
||||
if (work[VR_PartitionFSType] != fs->fs_type) {
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
/* Check whether volume base sector has benn changed or not */
|
||||
if (ld_dword(work + VR_PartitionStSec) != startBaseSect) {
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
/* Check whether volume base size hase been changed or not */
|
||||
if (ld_dword(work + VR_PartitionCtSec) != countBaseSect) {
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
/* Check whether volume cluster size has been changed or not */
|
||||
if (ld_word(work + VR_PartitionClstSz) != fs->csize) {
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
/* Check whether volume start cluster is cluster #3 or not */
|
||||
if (ld_dword(work + VR_PartitionCtClst) != fs->n_fatent) {
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
/* Check whether virtual partition overlimit */
|
||||
if (work[VR_PartitionCnt] > _MAX_VIRVOLUMES) {
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
static FRESULT FatfsCheckPercent(FATFS *fs, WORD i)
|
||||
{
|
||||
if ((CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst < fs->n_fatent) {
|
||||
fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
|
||||
fs->ct_clst = fs->n_fatent - ((CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst);
|
||||
} else if ((CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst == fs->n_fatent) {
|
||||
fs->st_clst = 0xFFFFFFFF;
|
||||
fs->ct_clst = 0xFFFFFFFF;
|
||||
} else {
|
||||
(void)f_unregvirfs(fs);
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
static FRESULT FatfsCheckPartClst(FATFS *fs, WORD i)
|
||||
{
|
||||
if (i == 0) {
|
||||
/* First virtual partition must start at cluster #3 */
|
||||
if ((CHILDFS(fs, i))->st_clst != 3) {
|
||||
(void)f_unregvirfs(fs);
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
} else {
|
||||
/* Check whether the current virtual partition is closely next to the previous virtual partition */
|
||||
if ((CHILDFS(fs, i))->st_clst != (CHILDFS(fs, (i - 1))->st_clst + CHILDFS(fs, (i - 1))->ct_clst)) {
|
||||
(void)f_unregvirfs(fs);
|
||||
return FR_MODIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
static void FatfsSetChildClst(BYTE *work, FATFS *fs, WORD i)
|
||||
{
|
||||
(CHILDFS(fs, i))->st_clst = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_StartClust);
|
||||
(CHILDFS(fs, i))->ct_clst = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_CountClust);
|
||||
}
|
||||
|
||||
/*
|
||||
* f_ckvtlpt :
|
||||
* Check the external SD virtual paritition sectors and read configure from it
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : The external SD configure is complete, all info has been set to the
|
||||
* each CHILD FATFS
|
||||
* - FR_NOT_MATCHED : The virtual partition's configure does not matched as current setting
|
||||
* - FR_MODIFIED : The virtual partition's configure has been destoried partly or completely
|
||||
* - FR_NOVIRPART : The external SD has not been apllied as virtual partition yet
|
||||
*
|
||||
* Others Return Value:
|
||||
* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
|
||||
* - FR_DENIED : The virtual partition feature has been shut down by switcher
|
||||
* - FR_INVALID_DRIVE : The drive index is error
|
||||
* - FR_DISK_ERR : A Disk error happend
|
||||
*/
|
||||
FRESULT f_checkvirpart(FATFS *fs, const TCHAR *path, BYTE vol)
|
||||
{
|
||||
FRESULT res;
|
||||
WORD i;
|
||||
DWORD virSect;
|
||||
DWORD tmp;
|
||||
BYTE pdrv;
|
||||
BYTE *work = NULL;
|
||||
CHAR label[_MAX_ENTRYLENGTH + 1];
|
||||
DWORD *labelTmp = NULL; /* to clear the compilation warning */
|
||||
|
||||
if (fs == NULL || (disk_status(fs->pdrv) & STA_NOINIT)) {
|
||||
return FR_INVAILD_FATFS; /* The object is invalid */
|
||||
}
|
||||
|
||||
/* Lock the filesystem object */
|
||||
res = find_volume(&path, &fs, FA_WRITE); /* Update the filesystem info to the parent fs */
|
||||
if (res != FR_OK) {
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
if (ISCHILD(fs)) {
|
||||
LEAVE_FF(fs, FR_INT_ERR);
|
||||
}
|
||||
/* Data will be save at the last reserve sector ,which is the front one of the fat base sector */
|
||||
virSect = fs->fatbase - 1;
|
||||
|
||||
pdrv = LD2PD(vol); /* Driver index */
|
||||
|
||||
work = (BYTE *)ff_memalloc(SS(fs));
|
||||
if (work == NULL) {
|
||||
LEAVE_FF(fs, FR_NOT_ENOUGH_CORE);
|
||||
}
|
||||
/* Check and vertify partition information */
|
||||
if (disk_read(pdrv, work, virSect, 1) != RES_OK) {
|
||||
res = FR_DISK_ERR;
|
||||
goto EXIT;
|
||||
} /* Load VBR */
|
||||
|
||||
res = FatfsCheckStart(work, fs, vol);
|
||||
if (res != FR_OK) {
|
||||
goto EXIT;
|
||||
}
|
||||
/* Check the virtual parition amount if matched current setting or not */
|
||||
fs->vir_amount = work[VR_PartitionCnt];
|
||||
res = f_regvirfs(fs);
|
||||
if (res != FR_OK) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
for (i = 0; i < _MAX_VIRVOLUMES; i++) {
|
||||
if (i < work[VR_PartitionCnt]) {
|
||||
if (work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] != 0x80) {
|
||||
(void)f_unregvirfs(fs);
|
||||
res = FR_MODIFIED;
|
||||
goto EXIT;
|
||||
}
|
||||
} else {
|
||||
if (work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] != 0x00) {
|
||||
(void)f_unregvirfs(fs);
|
||||
res = FR_MODIFIED;
|
||||
goto EXIT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
(void)memset_s(label, sizeof(label), 0, sizeof(label));
|
||||
|
||||
tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 0);
|
||||
labelTmp = (DWORD *)label;
|
||||
*labelTmp = tmp;
|
||||
tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 4);
|
||||
*((DWORD *)(label + 4)) = tmp;
|
||||
tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 8);
|
||||
*((DWORD *)(label + 8)) = tmp;
|
||||
tmp = ld_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 12);
|
||||
*((DWORD *)(label + 12)) = tmp;
|
||||
|
||||
if (f_checkname(label) != FR_OK) {
|
||||
(void)f_unregvirfs(fs);
|
||||
res = FR_MODIFIED;
|
||||
goto EXIT;
|
||||
}
|
||||
(void)memcpy_s((CHILDFS(fs, i))->namelabel, _MAX_ENTRYLENGTH + 1, label, _MAX_ENTRYLENGTH + 1);
|
||||
|
||||
FatfsSetChildClst(work, fs, i);
|
||||
|
||||
/* External SD setting has overlimit the whole partition cluster amount */
|
||||
if ((QWORD)(CHILDFS(fs, i))->st_clst + (QWORD)((CHILDFS(fs, i))->ct_clst) > (QWORD)fs->n_fatent) {
|
||||
(void)f_unregvirfs(fs);
|
||||
res = FR_MODIFIED;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
res = FatfsCheckPartClst(fs, i);
|
||||
if (res != FR_OK) {
|
||||
goto EXIT;
|
||||
}
|
||||
if (i == (work[VR_PartitionCnt] - 1)) {
|
||||
/*
|
||||
* If the external SD virtual partition percent exceeds the error tolerance based on current virtual
|
||||
* partition percent setting
|
||||
*/
|
||||
res = FatfsCheckPercent(fs, i);
|
||||
if (res != FR_OK) {
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXIT:
|
||||
ff_memfree(work);
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
static void FatfsClacPartInfo(FATFS *fs, DOUBLE virpartper, UINT i)
|
||||
{
|
||||
if (i == 0) {
|
||||
(CHILDFS(fs, i))->st_clst = 3;
|
||||
(CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
|
||||
g_fatVirPart.virtualinfo.virpartpercent[i]);
|
||||
|
||||
fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
|
||||
fs->ct_clst = fs->n_fatent - fs->st_clst;
|
||||
} else if (i != (fs->vir_amount - 1)) {
|
||||
(CHILDFS(fs, i))->st_clst = (CHILDFS(fs, (i - 1)))->st_clst + (CHILDFS(fs, (i - 1)))->ct_clst;
|
||||
(CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
|
||||
g_fatVirPart.virtualinfo.virpartpercent[i]);
|
||||
} else {
|
||||
(CHILDFS(fs, i))->st_clst = (CHILDFS(fs, (i - 1)))->st_clst + (CHILDFS(fs, (i - 1)))->ct_clst;
|
||||
if (virpartper <= (1 + _FLOAT_ACC) && virpartper >= (1 - _FLOAT_ACC)) {
|
||||
(CHILDFS(fs, i))->ct_clst = fs->n_fatent - (CHILDFS(fs, i))->st_clst;
|
||||
fs->st_clst = 0xFFFFFFFF;
|
||||
fs->ct_clst = 0xFFFFFFFF;
|
||||
} else {
|
||||
(CHILDFS(fs, i))->ct_clst = (DWORD)((fs->n_fatent - 3) *
|
||||
g_fatVirPart.virtualinfo.virpartpercent[i]);
|
||||
fs->st_clst = (CHILDFS(fs, i))->st_clst + (CHILDFS(fs, i))->ct_clst;
|
||||
fs->ct_clst = fs->n_fatent - fs->st_clst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* f_mkvtlpt:
|
||||
* Apply the current virtual partition's setting to external SD card and to the CHILD FATFS
|
||||
*
|
||||
* Acceptable Return Value:
|
||||
* - FR_OK : Successfully applied current setting to external SD card and
|
||||
* CHILD FATFS
|
||||
*
|
||||
* Others Return Value :
|
||||
* - FR_INVAILD_FATFS : The FATFS object has error or the info in it has been occuried
|
||||
* - FR_DENIED : The virtual partition feature has been shut down by switcher
|
||||
* - FR_INVALID_DRIVE : The drive index is error
|
||||
* - FR_DISK_ERR : A Disk error happend
|
||||
*/
|
||||
FRESULT f_makevirpart(FATFS *fs, const TCHAR *path, BYTE vol)
|
||||
{
|
||||
FRESULT res;
|
||||
DWORD virSect;
|
||||
DWORD startBaseSect, countBaseSect;
|
||||
DWORD tmp;
|
||||
CHAR label[_MAX_ENTRYLENGTH + 1];
|
||||
DWORD *labelTmp = NULL; /* to clear the compilation warning */
|
||||
UINT i;
|
||||
BYTE pdrv;
|
||||
BYTE *work = NULL;
|
||||
DOUBLE virpartper = 0.0;
|
||||
|
||||
if (fs == NULL || (disk_status(fs->pdrv) & STA_NOINIT)) {
|
||||
return FR_INVAILD_FATFS; /* The object is invalid */
|
||||
}
|
||||
|
||||
/* Lock the filesystem object */
|
||||
res = find_volume(&path, &fs, FA_WRITE); /* Update the filesystem info to the parent fs */
|
||||
if (res != FR_OK) {
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
/* Only available in FAT32 filesystem */
|
||||
if (ISCHILD(fs)) {
|
||||
LEAVE_FF(fs, FR_INVAILD_FATFS);
|
||||
}
|
||||
/* Data will be save at the last reserve sector,which is the front one of the fat base sector */
|
||||
virSect = fs->fatbase - 1;
|
||||
/* Search the fs index, which same as the volume index */
|
||||
pdrv = LD2PD(vol); /* Driver index */
|
||||
countBaseSect = LD2PC(vol); /* Volume Base Sectors Count */
|
||||
startBaseSect = LD2PS(vol); /* Volume Base Start Sector */
|
||||
|
||||
fs->vir_amount = g_fatVirPart.virtualinfo.virpartnum;
|
||||
res = f_regvirfs(fs);
|
||||
if (res != FR_OK) {
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
work = (BYTE *)ff_memalloc(SS(fs));
|
||||
if (work == NULL) {
|
||||
LEAVE_FF(fs, FR_NOT_ENOUGH_CORE);
|
||||
}
|
||||
/* Data Cluster is begin from the Cluster #3 to the last cluster */
|
||||
/* Cluster #0 #1 is for VBR, reserve sectors and fat */
|
||||
/* Cluster #2 is for root directory */
|
||||
(void)memset_s(work, SS(fs), 0, SS(fs));
|
||||
|
||||
for (i = 0; i < fs->vir_amount; i++) {
|
||||
/* Copy the Entry label and write to work sector's buffer */
|
||||
(void)memset_s(label, sizeof(label), 0, sizeof(label));
|
||||
(void)memcpy_s(label, _MAX_ENTRYLENGTH + 1, g_fatVirPart.virtualinfo.virpartname[i], _MAX_ENTRYLENGTH + 1);
|
||||
labelTmp = (DWORD *)label;
|
||||
tmp = *labelTmp;
|
||||
st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 0, tmp);
|
||||
tmp = *((DWORD *)(label + 4));
|
||||
st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 4, tmp);
|
||||
tmp = *((DWORD *)(label + 8));
|
||||
st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 8, tmp);
|
||||
tmp = *((DWORD *)(label + 12));
|
||||
st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_Entry + 12, tmp);
|
||||
|
||||
virpartper += g_fatVirPart.virtualinfo.virpartpercent[i];
|
||||
|
||||
(void)memcpy_s((CHILDFS(fs, i))->namelabel, _MAX_ENTRYLENGTH + 1, g_fatVirPart.virtualinfo.virpartname[i],
|
||||
_MAX_ENTRYLENGTH + 1);
|
||||
FatfsClacPartInfo(fs, virpartper, i);
|
||||
(CHILDFS(fs, i))->last_clst = (CHILDFS(fs, i))->st_clst - 1;
|
||||
work[VR_PARTITION + i * VR_ITEMSIZE + VR_Available] = 0x80;
|
||||
}
|
||||
|
||||
/* Set the data to sector */
|
||||
work[VR_PartitionCnt] = fs->vir_amount;
|
||||
work[VR_PartitionFSType] = fs->fs_type;
|
||||
st_dword(work + VR_PartitionStSec, startBaseSect);
|
||||
st_dword(work + VR_PartitionCtSec, countBaseSect);
|
||||
st_word(work + VR_PartitionClstSz, fs->csize);
|
||||
st_dword(work + VR_PartitionCtClst, fs->n_fatent);
|
||||
for (i = 0; i < fs->vir_amount; i++) {
|
||||
st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_StartClust,
|
||||
(CHILDFS(fs, i))->st_clst);
|
||||
st_dword(work + VR_PARTITION + i * VR_ITEMSIZE + VR_CountClust,
|
||||
(CHILDFS(fs, i))->ct_clst);
|
||||
}
|
||||
|
||||
/* ASCII for Keyword "LITE" */
|
||||
st_dword(work + VR_VertifyString, 0x4C495445);
|
||||
|
||||
/* Write into the data area */
|
||||
if (disk_write(pdrv, work, virSect, 1) != RES_OK) {
|
||||
(void)f_unregvirfs(fs);
|
||||
res = FR_DISK_ERR;
|
||||
}
|
||||
|
||||
ff_memfree(work);
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
FRESULT f_getvirfree(const TCHAR *path, DWORD *nclst, DWORD *cclst)
|
||||
{
|
||||
FATFS *fs = NULL;
|
||||
FRESULT res;
|
||||
DWORD clst, link;
|
||||
DWORD nfree;
|
||||
UINT i;
|
||||
DIR dj;
|
||||
|
||||
/* Find volume to Update the global FSINFO */
|
||||
res = find_volume(&path, &fs, 0);
|
||||
if (res != FR_OK) {
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
|
||||
/* Following the entry keyword, decide to replace the PARENT FATFS to CHILD FATFS or not */
|
||||
dj.obj.fs = fs;
|
||||
if (ISVIRPART(fs)) {
|
||||
/* Check the virtual partition top directory, and match the virtual fs */
|
||||
res = follow_virentry(&dj.obj, path);
|
||||
if (res == FR_INT_ERR) {
|
||||
LEAVE_FF(fs, res);
|
||||
}
|
||||
if (res == FR_OK) {
|
||||
fs = dj.obj.fs;
|
||||
}
|
||||
} else {
|
||||
/* Virtual Partition Feature was off, deny this operation */
|
||||
LEAVE_FF(fs, FR_DENIED);
|
||||
}
|
||||
|
||||
/* If current FATFS is a CHILD FATFS */
|
||||
if (ISCHILD(fs)) {
|
||||
/* If CHILD FATFS' free_clst is invaild, the scan the FAT and update it */
|
||||
if (fs->free_clst > fs->ct_clst) {
|
||||
dj.obj.fs = fs;
|
||||
fs->free_clst = fs->ct_clst;
|
||||
for (clst = fs->st_clst; clst < fs->st_clst + fs->ct_clst; clst++) {
|
||||
link = get_fat(&dj.obj, clst);
|
||||
if (link == 0) {
|
||||
continue;
|
||||
}
|
||||
fs->free_clst--;
|
||||
}
|
||||
}
|
||||
*nclst = fs->free_clst;
|
||||
*cclst = fs->ct_clst;
|
||||
LEAVE_FF(fs, FR_OK);
|
||||
} else {
|
||||
nfree = 0;
|
||||
if (fs->ct_clst == 0xFFFFFFFF) {
|
||||
LEAVE_FF(fs, FR_DENIED);
|
||||
}
|
||||
for (i = 0; i < fs->vir_amount; i++) {
|
||||
if (CHILDFS(fs, i)->free_clst > CHILDFS(fs, i)->ct_clst) {
|
||||
dj.obj.fs = CHILDFS(fs, i);
|
||||
CHILDFS(fs, i)->free_clst = CHILDFS(fs, i)->ct_clst;
|
||||
for (clst = CHILDFS(fs, i)->st_clst; clst < CHILDFS(fs, i)->st_clst + CHILDFS(fs, i)->ct_clst; clst++) {
|
||||
link = get_fat(&dj.obj, clst);
|
||||
if (link == 0) {
|
||||
continue;
|
||||
}
|
||||
CHILDFS(fs, i)->free_clst--;
|
||||
}
|
||||
}
|
||||
nfree += CHILDFS(fs, i)->free_clst;
|
||||
}
|
||||
*nclst = fs->free_clst - nfree;
|
||||
*cclst = fs->ct_clst;
|
||||
LEAVE_FF(fs, FR_OK);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user