10d163575Sopenharmony_ci/*
20d163575Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
30d163575Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
40d163575Sopenharmony_ci *
50d163575Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
60d163575Sopenharmony_ci * are permitted provided that the following conditions are met:
70d163575Sopenharmony_ci *
80d163575Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
90d163575Sopenharmony_ci *    conditions and the following disclaimer.
100d163575Sopenharmony_ci *
110d163575Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
120d163575Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
130d163575Sopenharmony_ci *    provided with the distribution.
140d163575Sopenharmony_ci *
150d163575Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
160d163575Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
170d163575Sopenharmony_ci *    permission.
180d163575Sopenharmony_ci *
190d163575Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200d163575Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
210d163575Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
220d163575Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
230d163575Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
240d163575Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
250d163575Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
260d163575Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
270d163575Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
280d163575Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
290d163575Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
300d163575Sopenharmony_ci */
310d163575Sopenharmony_ci
320d163575Sopenharmony_ci#include "mtd_partition.h"
330d163575Sopenharmony_ci#include "stdlib.h"
340d163575Sopenharmony_ci#include "stdio.h"
350d163575Sopenharmony_ci#include "pthread.h"
360d163575Sopenharmony_ci#include "mtd_list.h"
370d163575Sopenharmony_ci#include "los_config.h"
380d163575Sopenharmony_ci#include "los_mux.h"
390d163575Sopenharmony_ci#include "fs/driver.h"
400d163575Sopenharmony_ci#include "mtd/mtd_legacy_lite.h"
410d163575Sopenharmony_ci
420d163575Sopenharmony_ci#define DRIVER_NAME_ADD_SIZE    3
430d163575Sopenharmony_cipthread_mutex_t g_mtdPartitionLock = PTHREAD_MUTEX_INITIALIZER;
440d163575Sopenharmony_ci
450d163575Sopenharmony_cistatic VOID YaffsLockInit(VOID) __attribute__((weakref("yaffsfs_OSInitialisation")));
460d163575Sopenharmony_cistatic VOID YaffsLockDeinit(VOID) __attribute__((weakref("yaffsfs_OsDestroy")));
470d163575Sopenharmony_cistatic INT32 Jffs2LockInit(VOID) __attribute__((weakref("Jffs2MutexCreate")));
480d163575Sopenharmony_cistatic VOID Jffs2LockDeinit(VOID) __attribute__((weakref("Jffs2MutexDelete")));
490d163575Sopenharmony_ci
500d163575Sopenharmony_cipartition_param *g_nandPartParam = NULL;
510d163575Sopenharmony_cipartition_param *g_spinorPartParam = NULL;
520d163575Sopenharmony_cimtd_partition *g_spinorPartitionHead = NULL;
530d163575Sopenharmony_cimtd_partition *g_nandPartitionHead = NULL;
540d163575Sopenharmony_ci
550d163575Sopenharmony_ci#define RWE_RW_RW 0755
560d163575Sopenharmony_ci
570d163575Sopenharmony_cipartition_param *GetNandPartParam(VOID)
580d163575Sopenharmony_ci{
590d163575Sopenharmony_ci    return g_nandPartParam;
600d163575Sopenharmony_ci}
610d163575Sopenharmony_ci
620d163575Sopenharmony_cipartition_param *GetSpinorPartParam(VOID)
630d163575Sopenharmony_ci{
640d163575Sopenharmony_ci    return g_spinorPartParam;
650d163575Sopenharmony_ci}
660d163575Sopenharmony_ci
670d163575Sopenharmony_cimtd_partition *GetSpinorPartitionHead(VOID)
680d163575Sopenharmony_ci{
690d163575Sopenharmony_ci    return g_spinorPartitionHead;
700d163575Sopenharmony_ci}
710d163575Sopenharmony_ci
720d163575Sopenharmony_ci
730d163575Sopenharmony_cistatic VOID MtdNandParamAssign(partition_param *nandParam, const struct MtdDev *nandMtd)
740d163575Sopenharmony_ci{
750d163575Sopenharmony_ci    LOS_ListInit(&g_nandPartitionHead->node_info);
760d163575Sopenharmony_ci    /*
770d163575Sopenharmony_ci     * If the user do not want to use block mtd or char mtd ,
780d163575Sopenharmony_ci     * you can change the NANDBLK_NAME or NANDCHR_NAME to NULL.
790d163575Sopenharmony_ci     */
800d163575Sopenharmony_ci    nandParam->flash_mtd = (struct MtdDev *)nandMtd;
810d163575Sopenharmony_ci    nandParam->flash_ops = GetDevNandOps();
820d163575Sopenharmony_ci    nandParam->char_ops = GetMtdCharFops();
830d163575Sopenharmony_ci    nandParam->blockname = NANDBLK_NAME;
840d163575Sopenharmony_ci    nandParam->charname = NANDCHR_NAME;
850d163575Sopenharmony_ci    nandParam->partition_head = g_nandPartitionHead;
860d163575Sopenharmony_ci    nandParam->block_size = nandMtd->eraseSize;
870d163575Sopenharmony_ci}
880d163575Sopenharmony_ci
890d163575Sopenharmony_cistatic VOID MtdDeinitNandParam(VOID)
900d163575Sopenharmony_ci{
910d163575Sopenharmony_ci    if (YaffsLockDeinit != NULL) {
920d163575Sopenharmony_ci        YaffsLockDeinit();
930d163575Sopenharmony_ci    }
940d163575Sopenharmony_ci}
950d163575Sopenharmony_ci
960d163575Sopenharmony_cistatic partition_param *MtdInitNandParam(partition_param *nandParam)
970d163575Sopenharmony_ci{
980d163575Sopenharmony_ci    struct MtdDev *nandMtd = GetMtd("nand");
990d163575Sopenharmony_ci    if (nandMtd == NULL) {
1000d163575Sopenharmony_ci        return NULL;
1010d163575Sopenharmony_ci    }
1020d163575Sopenharmony_ci    if (nandParam == NULL) {
1030d163575Sopenharmony_ci        if (YaffsLockInit != NULL) {
1040d163575Sopenharmony_ci            YaffsLockInit();
1050d163575Sopenharmony_ci        }
1060d163575Sopenharmony_ci        nandParam = (partition_param *)zalloc(sizeof(partition_param));
1070d163575Sopenharmony_ci        if (nandParam == NULL) {
1080d163575Sopenharmony_ci            MtdDeinitNandParam();
1090d163575Sopenharmony_ci            return NULL;
1100d163575Sopenharmony_ci        }
1110d163575Sopenharmony_ci        g_nandPartitionHead = (mtd_partition *)zalloc(sizeof(mtd_partition));
1120d163575Sopenharmony_ci        if (g_nandPartitionHead == NULL) {
1130d163575Sopenharmony_ci            MtdDeinitNandParam();
1140d163575Sopenharmony_ci            free(nandParam);
1150d163575Sopenharmony_ci            return NULL;
1160d163575Sopenharmony_ci        }
1170d163575Sopenharmony_ci
1180d163575Sopenharmony_ci        MtdNandParamAssign(nandParam, nandMtd);
1190d163575Sopenharmony_ci    }
1200d163575Sopenharmony_ci
1210d163575Sopenharmony_ci    return nandParam;
1220d163575Sopenharmony_ci}
1230d163575Sopenharmony_ci
1240d163575Sopenharmony_cistatic VOID MtdNorParamAssign(partition_param *spinorParam, const struct MtdDev *spinorMtd)
1250d163575Sopenharmony_ci{
1260d163575Sopenharmony_ci    LOS_ListInit(&g_spinorPartitionHead->node_info);
1270d163575Sopenharmony_ci    /*
1280d163575Sopenharmony_ci     * If the user do not want to use block mtd or char mtd ,
1290d163575Sopenharmony_ci     * you can change the SPIBLK_NAME or SPICHR_NAME to NULL.
1300d163575Sopenharmony_ci     */
1310d163575Sopenharmony_ci    spinorParam->flash_mtd = (struct MtdDev *)spinorMtd;
1320d163575Sopenharmony_ci    spinorParam->flash_ops = GetDevSpinorOps();
1330d163575Sopenharmony_ci    spinorParam->char_ops = GetMtdCharFops();
1340d163575Sopenharmony_ci    spinorParam->blockname = SPIBLK_NAME;
1350d163575Sopenharmony_ci    spinorParam->charname = SPICHR_NAME;
1360d163575Sopenharmony_ci    spinorParam->partition_head = g_spinorPartitionHead;
1370d163575Sopenharmony_ci    spinorParam->block_size = spinorMtd->eraseSize;
1380d163575Sopenharmony_ci}
1390d163575Sopenharmony_ci
1400d163575Sopenharmony_cistatic VOID MtdDeinitSpinorParam(VOID)
1410d163575Sopenharmony_ci{
1420d163575Sopenharmony_ci    if (Jffs2LockDeinit != NULL) {
1430d163575Sopenharmony_ci        Jffs2LockDeinit();
1440d163575Sopenharmony_ci    }
1450d163575Sopenharmony_ci}
1460d163575Sopenharmony_ci
1470d163575Sopenharmony_cistatic partition_param *MtdInitSpinorParam(partition_param *spinorParam)
1480d163575Sopenharmony_ci{
1490d163575Sopenharmony_ci    struct MtdDev *spinorMtd = GetMtd("spinor");
1500d163575Sopenharmony_ci    if (spinorMtd == NULL) {
1510d163575Sopenharmony_ci        return NULL;
1520d163575Sopenharmony_ci    }
1530d163575Sopenharmony_ci    if (spinorParam == NULL) {
1540d163575Sopenharmony_ci        if (Jffs2LockInit != NULL) {
1550d163575Sopenharmony_ci            if (Jffs2LockInit() != 0) { /* create jffs2 lock failed */
1560d163575Sopenharmony_ci                return NULL;
1570d163575Sopenharmony_ci            }
1580d163575Sopenharmony_ci        }
1590d163575Sopenharmony_ci        spinorParam = (partition_param *)zalloc(sizeof(partition_param));
1600d163575Sopenharmony_ci        if (spinorParam == NULL) {
1610d163575Sopenharmony_ci            PRINT_ERR("%s, partition_param malloc failed\n", __FUNCTION__);
1620d163575Sopenharmony_ci            MtdDeinitSpinorParam();
1630d163575Sopenharmony_ci            return NULL;
1640d163575Sopenharmony_ci        }
1650d163575Sopenharmony_ci        g_spinorPartitionHead = (mtd_partition *)zalloc(sizeof(mtd_partition));
1660d163575Sopenharmony_ci        if (g_spinorPartitionHead == NULL) {
1670d163575Sopenharmony_ci            PRINT_ERR("%s, mtd_partition malloc failed\n", __FUNCTION__);
1680d163575Sopenharmony_ci            MtdDeinitSpinorParam();
1690d163575Sopenharmony_ci            free(spinorParam);
1700d163575Sopenharmony_ci            return NULL;
1710d163575Sopenharmony_ci        }
1720d163575Sopenharmony_ci
1730d163575Sopenharmony_ci        MtdNorParamAssign(spinorParam, spinorMtd);
1740d163575Sopenharmony_ci    }
1750d163575Sopenharmony_ci
1760d163575Sopenharmony_ci    return spinorParam;
1770d163575Sopenharmony_ci}
1780d163575Sopenharmony_ci
1790d163575Sopenharmony_ci/* According the flash-type to init the param of the partition. */
1800d163575Sopenharmony_cistatic INT32 MtdInitFsparParam(const CHAR *type, partition_param **fsparParam)
1810d163575Sopenharmony_ci{
1820d163575Sopenharmony_ci    if (strcmp(type, "nand") == 0) {
1830d163575Sopenharmony_ci        g_nandPartParam = MtdInitNandParam(g_nandPartParam);
1840d163575Sopenharmony_ci        *fsparParam = g_nandPartParam;
1850d163575Sopenharmony_ci    } else if (strcmp(type, "spinor") == 0 || strcmp(type, "cfi-flash") == 0) {
1860d163575Sopenharmony_ci        g_spinorPartParam = MtdInitSpinorParam(g_spinorPartParam);
1870d163575Sopenharmony_ci        *fsparParam = g_spinorPartParam;
1880d163575Sopenharmony_ci    } else {
1890d163575Sopenharmony_ci        return -EINVAL;
1900d163575Sopenharmony_ci    }
1910d163575Sopenharmony_ci
1920d163575Sopenharmony_ci    if ((*fsparParam == NULL) || ((VOID *)((*fsparParam)->flash_mtd) == NULL)) {
1930d163575Sopenharmony_ci        return -ENODEV;
1940d163575Sopenharmony_ci    }
1950d163575Sopenharmony_ci
1960d163575Sopenharmony_ci    return ENOERR;
1970d163575Sopenharmony_ci}
1980d163575Sopenharmony_ci
1990d163575Sopenharmony_ci/* According the flash-type to deinit the param of the partition. */
2000d163575Sopenharmony_cistatic INT32 MtdDeinitFsparParam(const CHAR *type)
2010d163575Sopenharmony_ci{
2020d163575Sopenharmony_ci    if (strcmp(type, "nand") == 0) {
2030d163575Sopenharmony_ci        MtdDeinitNandParam();
2040d163575Sopenharmony_ci        g_nandPartParam = NULL;
2050d163575Sopenharmony_ci    } else if (strcmp(type, "spinor") == 0 || strcmp(type, "cfi-flash") == 0) {
2060d163575Sopenharmony_ci        MtdDeinitSpinorParam();
2070d163575Sopenharmony_ci        g_spinorPartParam = NULL;
2080d163575Sopenharmony_ci    } else {
2090d163575Sopenharmony_ci        return -EINVAL;
2100d163575Sopenharmony_ci    }
2110d163575Sopenharmony_ci
2120d163575Sopenharmony_ci    return ENOERR;
2130d163575Sopenharmony_ci}
2140d163575Sopenharmony_ci
2150d163575Sopenharmony_cistatic INT32 AddParamCheck(UINT32 startAddr,
2160d163575Sopenharmony_ci                           const partition_param *param,
2170d163575Sopenharmony_ci                           UINT32 partitionNum,
2180d163575Sopenharmony_ci                           UINT32 length)
2190d163575Sopenharmony_ci{
2200d163575Sopenharmony_ci    UINT32 startBlk, endBlk;
2210d163575Sopenharmony_ci    mtd_partition *node = NULL;
2220d163575Sopenharmony_ci    if ((param->blockname == NULL) && (param->charname == NULL)) {
2230d163575Sopenharmony_ci        return -EINVAL;
2240d163575Sopenharmony_ci    }
2250d163575Sopenharmony_ci
2260d163575Sopenharmony_ci    if ((length == 0) || (length < param->block_size) ||
2270d163575Sopenharmony_ci        (((UINT64)(startAddr) + length) > param->flash_mtd->size)) {
2280d163575Sopenharmony_ci        return -EINVAL;
2290d163575Sopenharmony_ci    }
2300d163575Sopenharmony_ci
2310d163575Sopenharmony_ci    ALIGN_ASSIGN(length, startAddr, startBlk, endBlk, param->block_size);
2320d163575Sopenharmony_ci
2330d163575Sopenharmony_ci    if (startBlk > endBlk) {
2340d163575Sopenharmony_ci        return -EINVAL;
2350d163575Sopenharmony_ci    }
2360d163575Sopenharmony_ci    LOS_DL_LIST_FOR_EACH_ENTRY(node, &param->partition_head->node_info, mtd_partition, node_info) {
2370d163575Sopenharmony_ci        if ((node->start_block != 0) && (node->patitionnum == partitionNum)) {
2380d163575Sopenharmony_ci            return -EINVAL;
2390d163575Sopenharmony_ci        }
2400d163575Sopenharmony_ci        if ((startBlk > node->end_block) || (endBlk < node->start_block)) {
2410d163575Sopenharmony_ci            continue;
2420d163575Sopenharmony_ci        }
2430d163575Sopenharmony_ci        return -EINVAL;
2440d163575Sopenharmony_ci    }
2450d163575Sopenharmony_ci
2460d163575Sopenharmony_ci    return ENOERR;
2470d163575Sopenharmony_ci}
2480d163575Sopenharmony_ci
2490d163575Sopenharmony_cistatic INT32 BlockDriverRegisterOperate(mtd_partition *newNode,
2500d163575Sopenharmony_ci                                        const partition_param *param,
2510d163575Sopenharmony_ci                                        UINT32 partitionNum)
2520d163575Sopenharmony_ci{
2530d163575Sopenharmony_ci    INT32 ret;
2540d163575Sopenharmony_ci    size_t driverNameSize;
2550d163575Sopenharmony_ci
2560d163575Sopenharmony_ci    if (param->blockname != NULL) {
2570d163575Sopenharmony_ci        driverNameSize = strlen(param->blockname) + DRIVER_NAME_ADD_SIZE;
2580d163575Sopenharmony_ci        newNode->blockdriver_name = (CHAR *)malloc(driverNameSize);
2590d163575Sopenharmony_ci        if (newNode->blockdriver_name == NULL) {
2600d163575Sopenharmony_ci            return -ENOMEM;
2610d163575Sopenharmony_ci        }
2620d163575Sopenharmony_ci
2630d163575Sopenharmony_ci        ret = snprintf_s(newNode->blockdriver_name, driverNameSize,
2640d163575Sopenharmony_ci            driverNameSize - 1, "%s%u", param->blockname, partitionNum);
2650d163575Sopenharmony_ci        if (ret < 0) {
2660d163575Sopenharmony_ci            free(newNode->blockdriver_name);
2670d163575Sopenharmony_ci            newNode->blockdriver_name = NULL;
2680d163575Sopenharmony_ci            return -ENAMETOOLONG;
2690d163575Sopenharmony_ci        }
2700d163575Sopenharmony_ci
2710d163575Sopenharmony_ci        ret = register_blockdriver(newNode->blockdriver_name, param->flash_ops,
2720d163575Sopenharmony_ci            RWE_RW_RW, newNode);
2730d163575Sopenharmony_ci        if (ret) {
2740d163575Sopenharmony_ci            free(newNode->blockdriver_name);
2750d163575Sopenharmony_ci            newNode->blockdriver_name = NULL;
2760d163575Sopenharmony_ci            PRINT_ERR("register blkdev partition error\n");
2770d163575Sopenharmony_ci            return ret;
2780d163575Sopenharmony_ci        }
2790d163575Sopenharmony_ci    } else {
2800d163575Sopenharmony_ci        newNode->blockdriver_name = NULL;
2810d163575Sopenharmony_ci    }
2820d163575Sopenharmony_ci    return ENOERR;
2830d163575Sopenharmony_ci}
2840d163575Sopenharmony_ci
2850d163575Sopenharmony_cistatic INT32 CharDriverRegisterOperate(mtd_partition *newNode,
2860d163575Sopenharmony_ci                                       const partition_param *param,
2870d163575Sopenharmony_ci                                       UINT32 partitionNum)
2880d163575Sopenharmony_ci{
2890d163575Sopenharmony_ci    INT32 ret;
2900d163575Sopenharmony_ci    size_t driverNameSize;
2910d163575Sopenharmony_ci
2920d163575Sopenharmony_ci    if (param->charname != NULL) {
2930d163575Sopenharmony_ci        driverNameSize = strlen(param->charname) + DRIVER_NAME_ADD_SIZE;
2940d163575Sopenharmony_ci        newNode->chardriver_name = (CHAR *)malloc(driverNameSize);
2950d163575Sopenharmony_ci        if (newNode->chardriver_name == NULL) {
2960d163575Sopenharmony_ci            return -ENOMEM;
2970d163575Sopenharmony_ci        }
2980d163575Sopenharmony_ci
2990d163575Sopenharmony_ci        ret = snprintf_s(newNode->chardriver_name, driverNameSize,
3000d163575Sopenharmony_ci            driverNameSize - 1, "%s%u", param->charname, partitionNum);
3010d163575Sopenharmony_ci        if (ret < 0) {
3020d163575Sopenharmony_ci            free(newNode->chardriver_name);
3030d163575Sopenharmony_ci            newNode->chardriver_name = NULL;
3040d163575Sopenharmony_ci            return -ENAMETOOLONG;
3050d163575Sopenharmony_ci        }
3060d163575Sopenharmony_ci
3070d163575Sopenharmony_ci        ret = register_driver(newNode->chardriver_name, param->char_ops, RWE_RW_RW, newNode);
3080d163575Sopenharmony_ci        if (ret) {
3090d163575Sopenharmony_ci            PRINT_ERR("register chardev partition error\n");
3100d163575Sopenharmony_ci            free(newNode->chardriver_name);
3110d163575Sopenharmony_ci            newNode->chardriver_name = NULL;
3120d163575Sopenharmony_ci            return ret;
3130d163575Sopenharmony_ci        }
3140d163575Sopenharmony_ci    } else {
3150d163575Sopenharmony_ci        newNode->chardriver_name = NULL;
3160d163575Sopenharmony_ci    }
3170d163575Sopenharmony_ci    return ENOERR;
3180d163575Sopenharmony_ci}
3190d163575Sopenharmony_ci
3200d163575Sopenharmony_cistatic INT32 BlockDriverUnregister(mtd_partition *node)
3210d163575Sopenharmony_ci{
3220d163575Sopenharmony_ci    INT32 ret;
3230d163575Sopenharmony_ci
3240d163575Sopenharmony_ci    if (node->blockdriver_name != NULL) {
3250d163575Sopenharmony_ci        ret = unregister_blockdriver(node->blockdriver_name);
3260d163575Sopenharmony_ci        if (ret == -EBUSY) {
3270d163575Sopenharmony_ci            PRINT_ERR("unregister blkdev partition error:%d\n", ret);
3280d163575Sopenharmony_ci            return ret;
3290d163575Sopenharmony_ci        }
3300d163575Sopenharmony_ci        free(node->blockdriver_name);
3310d163575Sopenharmony_ci        node->blockdriver_name = NULL;
3320d163575Sopenharmony_ci    }
3330d163575Sopenharmony_ci    return ENOERR;
3340d163575Sopenharmony_ci}
3350d163575Sopenharmony_ci
3360d163575Sopenharmony_cistatic INT32 CharDriverUnregister(mtd_partition *node)
3370d163575Sopenharmony_ci{
3380d163575Sopenharmony_ci    INT32 ret;
3390d163575Sopenharmony_ci
3400d163575Sopenharmony_ci    if (node->chardriver_name != NULL) {
3410d163575Sopenharmony_ci        ret = unregister_driver(node->chardriver_name);
3420d163575Sopenharmony_ci        if (ret == -EBUSY) {
3430d163575Sopenharmony_ci            PRINT_ERR("unregister chardev partition error:%d\n", ret);
3440d163575Sopenharmony_ci            return ret;
3450d163575Sopenharmony_ci        }
3460d163575Sopenharmony_ci        free(node->chardriver_name);
3470d163575Sopenharmony_ci        node->chardriver_name = NULL;
3480d163575Sopenharmony_ci    }
3490d163575Sopenharmony_ci
3500d163575Sopenharmony_ci    return ENOERR;
3510d163575Sopenharmony_ci}
3520d163575Sopenharmony_ci
3530d163575Sopenharmony_ci/*
3540d163575Sopenharmony_ci * Attention: both startAddr and length should be aligned with block size.
3550d163575Sopenharmony_ci * If not, the actual start address and length won't be what you expected.
3560d163575Sopenharmony_ci */
3570d163575Sopenharmony_ciINT32 add_mtd_partition(const CHAR *type, UINT32 startAddr,
3580d163575Sopenharmony_ci                        UINT32 length, UINT32 partitionNum)
3590d163575Sopenharmony_ci{
3600d163575Sopenharmony_ci    INT32 ret;
3610d163575Sopenharmony_ci    mtd_partition *newNode = NULL;
3620d163575Sopenharmony_ci    partition_param *param = NULL;
3630d163575Sopenharmony_ci
3640d163575Sopenharmony_ci    if ((partitionNum >= CONFIG_MTD_PATTITION_NUM) || (type == NULL)) {
3650d163575Sopenharmony_ci        return -EINVAL;
3660d163575Sopenharmony_ci    }
3670d163575Sopenharmony_ci
3680d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_mtdPartitionLock);
3690d163575Sopenharmony_ci    if (ret != ENOERR) {
3700d163575Sopenharmony_ci        PRINT_ERR("%s %d, mutex lock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
3710d163575Sopenharmony_ci    }
3720d163575Sopenharmony_ci
3730d163575Sopenharmony_ci    ret = MtdInitFsparParam(type, &param);
3740d163575Sopenharmony_ci    if (ret != ENOERR) {
3750d163575Sopenharmony_ci        goto ERROR_OUT;
3760d163575Sopenharmony_ci    }
3770d163575Sopenharmony_ci
3780d163575Sopenharmony_ci    ret = AddParamCheck(startAddr, param, partitionNum, length);
3790d163575Sopenharmony_ci    if (ret != ENOERR) {
3800d163575Sopenharmony_ci        goto ERROR_OUT;
3810d163575Sopenharmony_ci    }
3820d163575Sopenharmony_ci
3830d163575Sopenharmony_ci    newNode = (mtd_partition *)zalloc(sizeof(mtd_partition));
3840d163575Sopenharmony_ci    if (newNode == NULL) {
3850d163575Sopenharmony_ci        (VOID)pthread_mutex_unlock(&g_mtdPartitionLock);
3860d163575Sopenharmony_ci        return -ENOMEM;
3870d163575Sopenharmony_ci    }
3880d163575Sopenharmony_ci
3890d163575Sopenharmony_ci    PAR_ASSIGNMENT(newNode, length, startAddr, partitionNum, param->flash_mtd, param->block_size);
3900d163575Sopenharmony_ci
3910d163575Sopenharmony_ci    ret = BlockDriverRegisterOperate(newNode, param, partitionNum);
3920d163575Sopenharmony_ci    if (ret) {
3930d163575Sopenharmony_ci        goto ERROR_OUT1;
3940d163575Sopenharmony_ci    }
3950d163575Sopenharmony_ci
3960d163575Sopenharmony_ci    ret = CharDriverRegisterOperate(newNode, param, partitionNum);
3970d163575Sopenharmony_ci    if (ret) {
3980d163575Sopenharmony_ci        goto ERROR_OUT2;
3990d163575Sopenharmony_ci    }
4000d163575Sopenharmony_ci
4010d163575Sopenharmony_ci    LOS_ListTailInsert(&param->partition_head->node_info, &newNode->node_info);
4020d163575Sopenharmony_ci    (VOID)LOS_MuxInit(&newNode->lock, NULL);
4030d163575Sopenharmony_ci
4040d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_mtdPartitionLock);
4050d163575Sopenharmony_ci    if (ret != ENOERR) {
4060d163575Sopenharmony_ci        PRINT_ERR("%s %d, mutex unlock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
4070d163575Sopenharmony_ci    }
4080d163575Sopenharmony_ci
4090d163575Sopenharmony_ci    return ENOERR;
4100d163575Sopenharmony_ciERROR_OUT2:
4110d163575Sopenharmony_ci    (VOID)BlockDriverUnregister(newNode);
4120d163575Sopenharmony_ciERROR_OUT1:
4130d163575Sopenharmony_ci    free(newNode);
4140d163575Sopenharmony_ciERROR_OUT:
4150d163575Sopenharmony_ci    (VOID)pthread_mutex_unlock(&g_mtdPartitionLock);
4160d163575Sopenharmony_ci    return ret;
4170d163575Sopenharmony_ci}
4180d163575Sopenharmony_ci
4190d163575Sopenharmony_cistatic INT32 DeleteParamCheck(UINT32 partitionNum,
4200d163575Sopenharmony_ci                              const CHAR *type,
4210d163575Sopenharmony_ci                              partition_param **param)
4220d163575Sopenharmony_ci{
4230d163575Sopenharmony_ci    if (strcmp(type, "nand") == 0) {
4240d163575Sopenharmony_ci        *param = g_nandPartParam;
4250d163575Sopenharmony_ci    } else if (strcmp(type, "spinor") == 0 || strcmp(type, "cfi-flash") == 0) {
4260d163575Sopenharmony_ci        *param = g_spinorPartParam;
4270d163575Sopenharmony_ci    } else {
4280d163575Sopenharmony_ci        PRINT_ERR("type error \n");
4290d163575Sopenharmony_ci        return -EINVAL;
4300d163575Sopenharmony_ci    }
4310d163575Sopenharmony_ci
4320d163575Sopenharmony_ci    if ((partitionNum >= CONFIG_MTD_PATTITION_NUM) ||
4330d163575Sopenharmony_ci        ((*param) == NULL) || ((*param)->flash_mtd == NULL)) {
4340d163575Sopenharmony_ci        return -EINVAL;
4350d163575Sopenharmony_ci    }
4360d163575Sopenharmony_ci    return ENOERR;
4370d163575Sopenharmony_ci}
4380d163575Sopenharmony_ci
4390d163575Sopenharmony_cistatic INT32 DeletePartitionUnregister(mtd_partition *node)
4400d163575Sopenharmony_ci{
4410d163575Sopenharmony_ci    INT32 ret;
4420d163575Sopenharmony_ci
4430d163575Sopenharmony_ci    ret = BlockDriverUnregister(node);
4440d163575Sopenharmony_ci    if (ret == -EBUSY) {
4450d163575Sopenharmony_ci        return ret;
4460d163575Sopenharmony_ci    }
4470d163575Sopenharmony_ci
4480d163575Sopenharmony_ci    ret = CharDriverUnregister(node);
4490d163575Sopenharmony_ci    if (ret == -EBUSY) {
4500d163575Sopenharmony_ci        return ret;
4510d163575Sopenharmony_ci    }
4520d163575Sopenharmony_ci
4530d163575Sopenharmony_ci    return ENOERR;
4540d163575Sopenharmony_ci}
4550d163575Sopenharmony_ci
4560d163575Sopenharmony_cistatic INT32 OsNodeGet(mtd_partition **node, UINT32 partitionNum, const partition_param *param)
4570d163575Sopenharmony_ci{
4580d163575Sopenharmony_ci    LOS_DL_LIST_FOR_EACH_ENTRY(*node, &param->partition_head->node_info, mtd_partition, node_info) {
4590d163575Sopenharmony_ci        if ((*node)->patitionnum == partitionNum) {
4600d163575Sopenharmony_ci            break;
4610d163575Sopenharmony_ci        }
4620d163575Sopenharmony_ci    }
4630d163575Sopenharmony_ci    if ((*node == NULL) || ((*node)->patitionnum != partitionNum) ||
4640d163575Sopenharmony_ci        ((*node)->mountpoint_name != NULL)) {
4650d163575Sopenharmony_ci        return -EINVAL;
4660d163575Sopenharmony_ci    }
4670d163575Sopenharmony_ci
4680d163575Sopenharmony_ci    return ENOERR;
4690d163575Sopenharmony_ci}
4700d163575Sopenharmony_ci
4710d163575Sopenharmony_cistatic INT32 OsResourceRelease(mtd_partition *node, const CHAR *type, partition_param *param)
4720d163575Sopenharmony_ci{
4730d163575Sopenharmony_ci    (VOID)LOS_MuxDestroy(&node->lock);
4740d163575Sopenharmony_ci    LOS_ListDelete(&node->node_info);
4750d163575Sopenharmony_ci    (VOID)memset_s(node, sizeof(mtd_partition), 0, sizeof(mtd_partition));
4760d163575Sopenharmony_ci    free(node);
4770d163575Sopenharmony_ci    (VOID)FreeMtd(param->flash_mtd);
4780d163575Sopenharmony_ci    if (LOS_ListEmpty(&param->partition_head->node_info)) {
4790d163575Sopenharmony_ci        free(param->partition_head);
4800d163575Sopenharmony_ci        param->partition_head = NULL;
4810d163575Sopenharmony_ci        free(param);
4820d163575Sopenharmony_ci
4830d163575Sopenharmony_ci        if (MtdDeinitFsparParam(type) != ENOERR) {
4840d163575Sopenharmony_ci            return -EINVAL;
4850d163575Sopenharmony_ci        }
4860d163575Sopenharmony_ci    }
4870d163575Sopenharmony_ci    return ENOERR;
4880d163575Sopenharmony_ci}
4890d163575Sopenharmony_ci
4900d163575Sopenharmony_ciINT32 delete_mtd_partition(UINT32 partitionNum, const CHAR *type)
4910d163575Sopenharmony_ci{
4920d163575Sopenharmony_ci    INT32 ret;
4930d163575Sopenharmony_ci    mtd_partition *node = NULL;
4940d163575Sopenharmony_ci    partition_param *param = NULL;
4950d163575Sopenharmony_ci
4960d163575Sopenharmony_ci    if (type == NULL) {
4970d163575Sopenharmony_ci        return -EINVAL;
4980d163575Sopenharmony_ci    }
4990d163575Sopenharmony_ci
5000d163575Sopenharmony_ci    ret = pthread_mutex_lock(&g_mtdPartitionLock);
5010d163575Sopenharmony_ci    if (ret != ENOERR) {
5020d163575Sopenharmony_ci        PRINT_ERR("%s %d, mutex lock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
5030d163575Sopenharmony_ci    }
5040d163575Sopenharmony_ci
5050d163575Sopenharmony_ci    ret = DeleteParamCheck(partitionNum, type, &param);
5060d163575Sopenharmony_ci    if (ret) {
5070d163575Sopenharmony_ci        PRINT_ERR("delete_mtd_partition param invalid\n");
5080d163575Sopenharmony_ci        (VOID)pthread_mutex_unlock(&g_mtdPartitionLock);
5090d163575Sopenharmony_ci        return ret;
5100d163575Sopenharmony_ci    }
5110d163575Sopenharmony_ci
5120d163575Sopenharmony_ci    ret = OsNodeGet(&node, partitionNum, param);
5130d163575Sopenharmony_ci    if (ret) {
5140d163575Sopenharmony_ci        (VOID)pthread_mutex_unlock(&g_mtdPartitionLock);
5150d163575Sopenharmony_ci        return ret;
5160d163575Sopenharmony_ci    }
5170d163575Sopenharmony_ci
5180d163575Sopenharmony_ci    ret = DeletePartitionUnregister(node);
5190d163575Sopenharmony_ci    if (ret) {
5200d163575Sopenharmony_ci        PRINT_ERR("DeletePartitionUnregister error:%d\n", ret);
5210d163575Sopenharmony_ci        (VOID)pthread_mutex_unlock(&g_mtdPartitionLock);
5220d163575Sopenharmony_ci        return ret;
5230d163575Sopenharmony_ci    }
5240d163575Sopenharmony_ci
5250d163575Sopenharmony_ci    ret = OsResourceRelease(node, type, param);
5260d163575Sopenharmony_ci    if (ret) {
5270d163575Sopenharmony_ci        PRINT_ERR("DeletePartitionUnregister error:%d\n", ret);
5280d163575Sopenharmony_ci        (VOID)pthread_mutex_unlock(&g_mtdPartitionLock);
5290d163575Sopenharmony_ci        return ret;
5300d163575Sopenharmony_ci    }
5310d163575Sopenharmony_ci
5320d163575Sopenharmony_ci    ret = pthread_mutex_unlock(&g_mtdPartitionLock);
5330d163575Sopenharmony_ci    if (ret != ENOERR) {
5340d163575Sopenharmony_ci        PRINT_ERR("%s %d, mutex unlock failed, error:%d\n", __FUNCTION__, __LINE__, ret);
5350d163575Sopenharmony_ci    }
5360d163575Sopenharmony_ci    return ENOERR;
5370d163575Sopenharmony_ci}
5380d163575Sopenharmony_ci
539