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, ¶m->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, ¶m); 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(¶m->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, ¶m->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(¶m->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, ¶m); 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