diff --git a/components/fs/littlefs/lfs_adapter.c b/components/fs/littlefs/lfs_adapter.c index 135704e6..1e80f672 100644 --- a/components/fs/littlefs/lfs_adapter.c +++ b/components/fs/littlefs/lfs_adapter.c @@ -32,6 +32,7 @@ #define _GNU_SOURCE 1 #include "lfs_adapter.h" #include "los_config.h" +#include "los_fs.h" #include "vfs_files.h" #include "vfs_operations.h" #include "vfs_partition.h" @@ -39,8 +40,76 @@ #include "vfs_mount.h" #include "securec.h" -struct dirent g_nameValue; -static pthread_mutex_t g_FslocalMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t g_fsLocalMutex = PTHREAD_MUTEX_INITIALIZER; + +static struct PartitionCfg g_partitionCfg; +static struct lfs_config g_lfsCfg; +static struct DeviceDesc *g_lfsDevice = NULL; + +static uint32_t LfsGetStartAddr(int partition) +{ + if (g_lfsDevice == NULL) { + struct DeviceDesc *device = NULL; + for (device = getDeviceList(); device != NULL; device = device->dNext) { + if (strcmp(device->dFsType, "littlefs") == 0) { + g_lfsDevice = device; + break; + } + } + } + + if ((g_lfsDevice == NULL) || (partition >= g_lfsDevice->dPartNum)) { + return INVALID_DEVICE_ADDR; + } + + return g_lfsDevice->dAddrArray[partition]; +} + +WEAK int littlefs_block_read(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, void *dst, lfs_size_t size) +{ + UINT32 addr = c->block_size * block + off; + UINT32 startaddr = LfsGetStartAddr((int)c->context); + if (startaddr == INVALID_DEVICE_ADDR) { + return -1; + } + addr += startaddr; + + return (g_partitionCfg.readFunc)((int)c->context, &addr, dst, size); +} + +WEAK int littlefs_block_write(const struct lfs_config *c, lfs_block_t block, + lfs_off_t off, const void *dst, lfs_size_t size) +{ + UINT32 addr = c->block_size * block + off; + UINT32 startaddr = LfsGetStartAddr((int)c->context); + if (startaddr == INVALID_DEVICE_ADDR) { + return -1; + } + + addr += startaddr; + + return (g_partitionCfg.writeFunc)((int)c->context, &addr, dst, size); +} + +WEAK int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block) +{ + UINT32 addr = c->block_size * block; + UINT32 startaddr = LfsGetStartAddr((int)c->context); + if (startaddr == INVALID_DEVICE_ADDR) { + return -1; + } + + addr += startaddr; + + return (g_partitionCfg.eraseFunc)((int)c->context, addr, c->block_size); +} + +WEAK int littlefs_block_sync(const struct lfs_config *c) +{ + (void)c; + return 0; +} static int ConvertFlagToLfsOpenFlag (int oflags) { @@ -82,6 +151,28 @@ static int LittlefsErrno(int result) return (result < 0) ? -result : result; } +void LfsConfigAdapter(struct PartitionCfg *pCfg, struct lfs_config *lfsCfg) +{ + lfsCfg->context = (void *)pCfg->partNo; + + lfsCfg->read_size = pCfg->readSize; + lfsCfg->prog_size = pCfg->writeSize; + lfsCfg->cache_size = pCfg->cacheSize; + lfsCfg->block_cycles = pCfg->blockCycles; + lfsCfg->lookahead_size = pCfg->lookaheadSize; + lfsCfg->block_size = pCfg->blockSize; + lfsCfg->block_count = pCfg->blockCount; + + lfsCfg->read = littlefs_block_read; + lfsCfg->prog = littlefs_block_write; + lfsCfg->erase = littlefs_block_erase; + lfsCfg->sync = littlefs_block_sync; + + g_partitionCfg.readFunc = pCfg->readFunc; + g_partitionCfg.writeFunc = pCfg->writeFunc; + g_partitionCfg.eraseFunc = pCfg->eraseFunc; +} + int LfsMount(struct MountPoint *mp, unsigned long mountflags, const void *data) { int ret; @@ -102,14 +193,15 @@ int LfsMount(struct MountPoint *mp, unsigned long mountflags, const void *data) (void)memset_s(mountHdl, sizeof(lfs_t), 0, sizeof(lfs_t)); mp->mData = (void *)mountHdl; - ret = lfs_mount((lfs_t *)mp->mData, (struct lfs_config *)data); + LfsConfigAdapter((struct PartitionCfg *)data, &g_lfsCfg); + + ret = lfs_mount((lfs_t *)mp->mData, &g_lfsCfg); if (ret != 0) { - ret = lfs_format((lfs_t *)mp->mData, (struct lfs_config*)data); + ret = lfs_format((lfs_t *)mp->mData, &g_lfsCfg); if (ret == 0) { - ret = lfs_mount((lfs_t *)mp->mData, (struct lfs_config*)data); + ret = lfs_mount((lfs_t *)mp->mData, &g_lfsCfg); } } - if (ret != 0) { free(mountHdl); errno = LittlefsErrno(ret); @@ -278,7 +370,7 @@ int LfsReaddir(struct Dir *dir, struct dirent *dent) ret = lfs_dir_read(lfs, dirInfo, &lfsInfo); if (ret == TRUE) { - pthread_mutex_lock(&g_FslocalMutex); + pthread_mutex_lock(&g_fsLocalMutex); (void)strncpy_s(dent->d_name, sizeof(dent->d_name), lfsInfo.name, strlen(lfsInfo.name) + 1); if (lfsInfo.type == LFS_TYPE_DIR) { dent->d_type = DT_DIR; @@ -287,7 +379,7 @@ int LfsReaddir(struct Dir *dir, struct dirent *dent) } dent->d_reclen = lfsInfo.size; - pthread_mutex_unlock(&g_FslocalMutex); + pthread_mutex_unlock(&g_fsLocalMutex); return LOS_OK; } @@ -467,9 +559,9 @@ int LfsClose(struct File *file) return (int)LOS_NOK; } - pthread_mutex_lock(&g_FslocalMutex); + pthread_mutex_lock(&g_fsLocalMutex); ret = lfs_file_close((lfs_t *)mp->mData, lfsHandle); - pthread_mutex_unlock(&g_FslocalMutex); + pthread_mutex_unlock(&g_fsLocalMutex); if (ret != 0) { errno = LittlefsErrno(ret); @@ -559,6 +651,23 @@ int LfsSync(struct File *file) return ret; } +int LfsFormat(const char *partName, void *privData) +{ + int ret; + lfs_t lfs = {0}; + + (void)partName; + + LfsConfigAdapter((struct PartitionCfg *)privData, &g_lfsCfg); + + ret = lfs_format(&lfs, &g_lfsCfg); + if (ret != 0) { + errno = LittlefsErrno(ret); + ret = LOS_NOK; + } + return ret; +} + static struct MountOps g_lfsMnt = { .mount = LfsMount, .umount = LfsUmount, @@ -587,7 +696,7 @@ static struct FileOps g_lfsFops = { static struct FsManagement g_lfsMgt = { .fdisk = NULL, - .format = NULL, + .format = LfsFormat, }; void LfsInit(void) diff --git a/components/fs/littlefs/lfs_adapter.h b/components/fs/littlefs/lfs_adapter.h index fa05e21d..e095f99e 100644 --- a/components/fs/littlefs/lfs_adapter.h +++ b/components/fs/littlefs/lfs_adapter.h @@ -45,6 +45,6 @@ #include "pthread.h" #define INVALID_FD (-1) - +#define INVALID_DEVICE_ADDR ((uint32_t)-1) void LfsInit(void); #endif /* _LFS_ADAPTER_H_ */ diff --git a/components/fs/vfs/los_fs.h b/components/fs/vfs/los_fs.h index 8bc6af20..f581a1d6 100644 --- a/components/fs/vfs/los_fs.h +++ b/components/fs/vfs/los_fs.h @@ -82,6 +82,26 @@ int LOS_FsUmount2(const char *target, int flag); int LOS_FsMount(const char *source, const char *target, const char *fsType, unsigned long mountflags, const void *data); + +struct PartitionCfg { + /* partition low-level read func */ + int (*readFunc)(int partition, UINT32 *offset, void *buf, UINT32 size); + /* partition low-level write func */ + int (*writeFunc)(int partition, UINT32 *offset, const void *buf, UINT32 size); + /* partition low-level erase func */ + int (*eraseFunc)(int partition, UINT32 offset, UINT32 size); + + int readSize; /* size of a block read */ + int writeSize; /* size of a block write */ + int blockSize; /* size of an erasable block */ + int blockCount; /* number of partition blocks */ + int cacheSize; /* size of block caches */ + + int partNo; /* partition number */ + int lookaheadSize; /* lookahead size */ + int blockCycles; /* block cycles */ +}; + /* * @brief Divide the device into partitions. * @@ -93,6 +113,7 @@ int LOS_FsMount(const char *source, const char *target, * @param lengthArray List of partition size. For example: * [0x10000000, 0x2000000], 256M and 512M partitions will be created and * left all will not allocated. + * @param addrArray List of partition start addr, partition num same as lengthArray * @param partNum Length of 'lengthArray'. * * @return Return LOS_NOK if error. Return LOS_OK if success. @@ -103,8 +124,8 @@ int LOS_FsMount(const char *source, const char *target, * The name is a combination of: 'deviceName'+'p'+'partitionId', * such as "emmc0p0", "emmc0p1", "emmc0p2"... */ -int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, - int partnum); +int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, int *addrArray, + int partNum); /* * @brief Format a partition. diff --git a/components/fs/vfs/vfs_partition.c b/components/fs/vfs/vfs_partition.c index 39e2d091..f86a27f9 100644 --- a/components/fs/vfs/vfs_partition.c +++ b/components/fs/vfs/vfs_partition.c @@ -37,6 +37,8 @@ #include "stdlib.h" #include "string.h" +static struct DeviceDesc *g_deviceList = NULL; + int GetPartIdByPartName(const char *partName) { if (partName == NULL) { @@ -67,16 +69,86 @@ int GetDevIdByDevName(const char *dev) return (int)LOS_NOK; } -int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, - int partnum) +struct DeviceDesc *getDeviceList(VOID) +{ + return g_deviceList; +} + +static int AddDevice(const char *dev, const char *fsType, int *lengthArray, int *addrArray, + int partNum) +{ + struct DeviceDesc *prev = NULL; + for (prev = g_deviceList; prev != NULL; prev = prev->dNext) { + if (strcmp(prev->dDev, dev) == 0) { + errno = -EEXIST; + return LOS_NOK; + } + } + + if (addrArray == NULL) { + errno = -EFAULT; + return LOS_NOK; + } + + prev = (struct DeviceDesc *)malloc(sizeof(struct DeviceDesc)); + if (prev == NULL) { + errno = -ENOMEM; + return LOS_NOK; + } + prev->dDev = strdup(dev); + prev->dFsType = strdup(fsType); + prev->dAddrArray = (int *)malloc(partNum * sizeof(int)); + if (prev->dDev == NULL || prev->dFsType == NULL || prev->dAddrArray == NULL) { + goto errout; + } + (void)memcpy_s(prev->dAddrArray, partNum * sizeof(int), addrArray, partNum * sizeof(int)); + + if (lengthArray != NULL) { + prev->dLengthArray = (int *)malloc(partNum * sizeof(int)); + if (prev->dLengthArray == NULL) { + goto errout; + } + (void)memcpy_s(prev->dLengthArray, partNum * sizeof(int), lengthArray, partNum * sizeof(int)); + } + + prev->dNext = g_deviceList; + prev->dPartNum = partNum; + g_deviceList = prev; + return LOS_OK; +errout: + if (prev->dDev != NULL) { + free((void *)prev->dDev); + } + if (prev->dFsType != NULL) { + free((void *)prev->dFsType); + } + if (prev->dAddrArray != NULL) { + free((void *)prev->dAddrArray); + } + if (prev->dLengthArray != NULL) { + free((void *)prev->dLengthArray); + } + + free(prev); + errno = -ENOMEM; + return LOS_NOK; +} + + +int LOS_DiskPartition(const char *dev, const char *fsType, int *lengthArray, int *addrArray, + int partNum) { int ret = (int)LOS_NOK; struct FsMap *fMap = VfsFsMapGet(fsType); if ((fMap != NULL) && (fMap->fsMgt != NULL) && (fMap->fsMgt->fdisk != NULL)) { - ret = fMap->fsMgt->fdisk(dev, lengthArray, partnum); + ret = fMap->fsMgt->fdisk(dev, lengthArray, partNum); + if (ret == LOS_NOK) { + return ret; + } } + ret = AddDevice(dev, fsType, lengthArray, addrArray, partNum); return ret; } @@ -100,5 +172,6 @@ int LOS_PartitionFormat(const char *partName, char *fsType, void *data) (fMap->fsMgt->format != NULL)) { ret = fMap->fsMgt->format(partName, data); } + return ret; } diff --git a/components/fs/vfs/vfs_partition.h b/components/fs/vfs/vfs_partition.h index 6edbefbf..b570fb94 100644 --- a/components/fs/vfs/vfs_partition.h +++ b/components/fs/vfs/vfs_partition.h @@ -31,6 +31,8 @@ #ifndef _VFS_PARTITION_H_ #define _VFS_PARTITION_H_ +#include "los_compiler.h" + #ifdef __cplusplus #if __cplusplus extern "C" { @@ -41,6 +43,19 @@ extern "C" { int GetPartIdByPartName(const char *partName); int GetDevIdByDevName(const char *dev); +struct DeviceDesc *getDeviceList(void); + +struct DeviceDesc { + struct FsMap *dFs; /* file system info */ + struct DeviceDesc *dNext; /* point to next mount point */ + const char *dPath; /* target path, /system, /usr, etc. */ + const char *dDev; /* device, "emmc0p0", "emmc0p1", etc. */ + void *dData; /* specific file system handle */ + const char *dFsType; /* file system type */ + int *dLengthArray; /* point to device partitions length array */ + int *dAddrArray; /* point to device partitions address array */ + int dPartNum; /* number of device partitions */ +}; #ifdef __cplusplus #if __cplusplus