[Feature][ZXW-88]merge P50 version
Only Configure: No
Affected branch: master
Affected module: unknown
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No
Change-Id: I34667719d9e0e7e29e8e4368848601cde0a48408
diff --git a/ap/lib/libmtd/mtd.c b/ap/lib/libmtd/mtd.c
new file mode 100755
index 0000000..5754368
--- /dev/null
+++ b/ap/lib/libmtd/mtd.c
@@ -0,0 +1,819 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <mtd/mtd-abi.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include "mtd_api.h"
+
+#define MTD_PATH_LENGTH_MAX (256)
+
+static ssize_t readn(int fd, void *vptr, size_t n);
+static ssize_t writen(int fd, const void *vptr, size_t n);
+
+/*******************************************************************************
+ * 内部函数/mtd_private.h *
+ *******************************************************************************/
+/**
+ * @brief 从文件描述符读取数据
+ * @param fd 入参,文件描述符
+ * @param vptr 出参,数据缓冲区
+ * @param n 入参,内容字节数
+ * @return 成功返回成功读取的字节数,失败返回-1
+ * @retval
+ * @note 封装read接口,读取被打断时会重试直到全部读取成功
+ * @warning
+ */
+static ssize_t readn(int fd, void *vptr, size_t n)
+{
+ size_t nleft;
+ ssize_t nread;
+ char *ptr;
+
+ ptr = vptr;
+ nleft = n;
+ while (nleft > 0)
+ {
+ if ((nread = read(fd, ptr, nleft)) < 0)
+ {
+ if (errno == EINTR)
+ {
+ nread = 0; /* and call read() again */
+ }
+ else
+ {
+ return (-1);
+ }
+ }
+ else if (nread == 0)
+ {
+ break; /* EOF */
+ }
+
+ nleft -= nread;
+ ptr += nread;
+ }
+ return (n - nleft); /* return >= 0 */
+}
+
+/**
+ * @brief 向文件描述符写入数据
+ * @param fd 入参,文件描述符
+ * @param vptr 入参,数据缓冲区
+ * @param n 入参,内容字节数
+ * @return 成功返回成功写入的字节数,失败返回-1
+ * @retval
+ * @note 封装write接口,写入被打断时会重试直到全部写入成功
+ * @warning
+ */
+static ssize_t writen(int fd, const void *vptr, size_t n)
+{
+ size_t nleft;
+ ssize_t nwritten;
+ const char *ptr;
+
+ ptr = vptr;
+ nleft = n;
+ while (nleft > 0)
+ {
+ nwritten = write(fd, ptr, nleft);
+ if (nwritten < 0)
+ {
+ if (errno == EINTR)
+ {
+ nwritten = 0; /* call write() again */
+ }
+ else
+ {
+ return (-1); /* error */
+ }
+ }
+ else if (nwritten == 0)
+ {
+ break;
+ }
+
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+ return (n - nleft); /* return >= 0 */
+}
+
+/*******************************************************************************
+ * 外部函数定义 *
+ *******************************************************************************/
+int mtd_find(const char *i_parti_name, device_type_t device_type, char *o_mtd_path, unsigned int o_mtd_path_len)
+{
+ FILE *fp_mtd = 0;
+ char buf[128];
+ char *line_str;
+
+ if (!o_mtd_path_len)
+ {
+ return -1;
+ }
+
+ fp_mtd = fopen("/proc/mtd", "r+");
+ if (NULL == fp_mtd)
+ {
+ printf("[libmtd]: mtd_find, open file error:%s", strerror(errno));
+ return -1;
+ }
+ // printf("[libmtd]: partition name:%s\n", i_parti_name);
+
+ while (1)
+ {
+ int matches = 0;
+ char mtdname[64] = {0};
+ int mtdnum = 0;
+ unsigned int mtdsize, mtderasesize;
+ memset(buf, 0, sizeof(buf));
+ line_str = fgets(buf, sizeof(buf) - 1, fp_mtd);
+
+ if (NULL == line_str)
+ {
+ printf("[libmtd]: mtd_find, get info from mtd error:%s\n", strerror(errno));
+ fclose(fp_mtd);
+ return -1;
+ }
+ // mtd5: 00100000 00020000 "fotaflag"
+ matches = sscanf(buf, "mtd%d: %x %x \"%63[^\"]",
+ &mtdnum, &mtdsize, &mtderasesize, mtdname);
+ mtdname[63] = '\0';
+
+ if ((matches == 4) && (strcmp(mtdname, i_parti_name) == 0))
+ {
+ memset(o_mtd_path, 0, o_mtd_path_len);
+ if (device_type == DEVICE_MTD_BLOCK)
+ {
+ snprintf(o_mtd_path, o_mtd_path_len, "/dev/mtdblock%d", mtdnum);
+ }
+ else if (device_type == DEVICE_MTD)
+ {
+ snprintf(o_mtd_path, o_mtd_path_len, "/dev/mtd%d", mtdnum);
+ }
+ else if (device_type == DEVICE_ZFTL)
+ {
+ snprintf(o_mtd_path, o_mtd_path_len, "/dev/zftl%d", mtdnum);
+ }
+ else
+ {
+ printf("[libmtd]: mtd_find, unknown device type %d\n", device_type);
+ fclose(fp_mtd);
+ return -1;
+ }
+ // printf("[libmtd]: o_mtd_path=[%s]\n", o_mtd_path);
+ break;
+ }
+ }
+ fclose(fp_mtd);
+ return 0;
+}
+
+int mtd_get_info(int fd, struct mtd_info_user *info)
+{
+ if (0 != ioctl(fd, MEMGETINFO, info))
+ {
+ printf("[libmtd]: mtd_get_info, get fd(%d) info error, %s\n", fd, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+int mtd_block_isbad(int fd, off_t offset)
+{
+ int ret = 0;
+ ret = ioctl(fd, MEMGETBADBLOCK, &offset);
+ if (ret > 0)
+ {
+ printf("[libmtd]: mtd_block_isbad, bad block at 0x%lx, ret = %d\n", offset, ret);
+ ret = 1;
+ }
+ else if (ret < 0)
+ {
+ printf("[libmtd]: mtd_block_isbad, ioctl(MEMGETBADBLOCK) error at 0x%lx, %s, ret = %d\n", offset, strerror(errno), ret);
+ ret = -1;
+ }
+ return ret;
+}
+
+int mtd_erase_partition(const char *partition_name)
+{
+ int ret = 0;
+ char mtd_path[MTD_PATH_LENGTH_MAX] = {0};
+ int fd_mtd = -1;
+
+ struct mtd_info_user meminfo = {0};
+ struct erase_info_user64 erase_info = {0};
+
+ if (NULL == partition_name)
+ {
+ return -1;
+ }
+
+ ret = mtd_find(partition_name, DEVICE_MTD, mtd_path, MTD_PATH_LENGTH_MAX);
+ if (ret < 0)
+ {
+ printf("[libmtd]: mtd_erase_partition, mtd_find %s failed\n", partition_name);
+ ret = -1;
+ goto out;
+ }
+ fd_mtd = open(mtd_path, O_RDWR);
+ if (fd_mtd < 0)
+ {
+ printf("[libmtd]: mtd_erase_partition, open %s error, %s\n", partition_name, strerror(errno));
+ return -1;
+ }
+ ret = mtd_get_info(fd_mtd, &meminfo);
+ if (ret < 0)
+ {
+ printf("[libmtd]: mtd_erase_partition, get %s info error, %s\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ erase_info.length = meminfo.erasesize;
+ for (erase_info.start = 0; erase_info.start < meminfo.size; erase_info.start += meminfo.erasesize)
+ {
+ ret = mtd_block_isbad(fd_mtd, erase_info.start);
+ if (1 == ret)
+ {
+ continue;
+ }
+ else if (-1 == ret)
+ {
+ printf("[libmtd]: mtd_erase_partition, mtd_block_isbad %s error\n", partition_name);
+ goto out;
+ }
+
+ if (0 != ioctl(fd_mtd, MEMERASE64, &erase_info))
+ {
+ printf("[libmtd]: mtd_erase_partition, erasing %s failure at 0x%llx\n", partition_name, erase_info.start);
+ if (ioctl(fd_mtd, MEMSETBADBLOCK, &(erase_info.start)) < 0)
+ {
+ printf("[libmtd]: mtd_erase_partition, mark %s bad block error, %s\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ continue;
+ }
+ }
+ ret = 0;
+out:
+ if (fd_mtd >= 0)
+ {
+ close(fd_mtd);
+ }
+ return ret;
+}
+
+int mtd_write_partition(const char *partition_name, const char *image_file)
+{
+ int ret = 0;
+ ssize_t wr_len;
+ char mtd_path[MTD_PATH_LENGTH_MAX] = {0};
+ int fd_mtd = -1;
+ struct mtd_info_user meminfo = {0};
+
+ off_t data_size = 0;
+ off_t index = 0;
+ off_t fd_img_index = 0;
+ int fd_img = -1;
+ char *buf = NULL;
+ struct stat statbuff = {0};
+
+ if (NULL == partition_name || NULL == image_file)
+ {
+ return -1;
+ }
+
+ ret = mtd_find(partition_name, DEVICE_MTD, mtd_path, MTD_PATH_LENGTH_MAX);
+ if (ret < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, mtd_find %s failed\n", partition_name);
+ ret = -1;
+ goto out;
+ }
+ fd_mtd = open(mtd_path, O_RDWR);
+ if (fd_mtd < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, open %s error, %s\n", partition_name, strerror(errno));
+ return -1;
+ }
+ ret = mtd_get_info(fd_mtd, &meminfo);
+ if (ret < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, get %s info error, %s\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ if (stat(image_file, &statbuff) < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, stat %s failed, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ fd_img = open(image_file, O_RDONLY);
+ if (fd_img < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, open %s failed, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ buf = (char *)malloc(meminfo.erasesize);
+ if (!buf)
+ {
+ printf("[libmtd]: mtd_write_partition, malloc failed\n");
+ ret = -1;
+ goto out;
+ }
+
+ for (index = 0; index < meminfo.size && fd_img_index < statbuff.st_size; index += meminfo.erasesize)
+ {
+ ret = mtd_block_isbad(fd_mtd, index);
+ if (1 == ret)
+ {
+ continue;
+ }
+ else if (-1 == ret)
+ {
+ printf("[libmtd]: mtd_write_partition, mtd_block_isbad %s error,at 0x%llx\n", partition_name, index);
+ goto out;
+ }
+
+ if (lseek(fd_img, fd_img_index, SEEK_SET) < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, lseek %s error = %s!\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ if (fd_img_index + meminfo.erasesize > statbuff.st_size)
+ {
+ data_size = statbuff.st_size - fd_img_index;
+ }
+ else
+ {
+ data_size = meminfo.erasesize;
+ }
+ wr_len = readn(fd_img, buf, (size_t)data_size);
+ if (wr_len < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, read %s error, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ fd_img_index += data_size;
+
+ if (lseek(fd_mtd, index, SEEK_SET) < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, lseek %s error = %s!\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ wr_len = writen(fd_mtd, buf, (size_t)data_size);
+ if (wr_len < 0)
+ {
+ printf("[libmtd]: mtd_write_partition, write %s error, %s\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ memset(buf, 0xFF, meminfo.erasesize);
+ }
+ if (fd_img_index < statbuff.st_size)
+ {
+ printf("[libmtd]: mtd_write_partition, No space left, writelen=0x%lx, filesize=0x%lx\n", fd_img_index, statbuff.st_size);
+ ret = -1;
+ goto out;
+ }
+ ret = 0;
+out:
+ if (fd_mtd >= 0)
+ {
+ close(fd_mtd);
+ }
+
+ if (buf != NULL)
+ {
+ // memset(buf, 0xFF, meminfo.erasesize);
+ free(buf);
+ }
+
+ if (fd_img >= 0)
+ {
+ close(fd_img);
+ }
+
+ return ret;
+}
+
+int mtd_erase_offset(int fd, off_t offset)
+{
+ struct mtd_info_user meminfo = {0};
+ struct erase_info_user64 erase_info = {0};
+
+ if (fd < 0)
+ {
+ printf("[libmtd]: mtd_erase_offset, fd(%d) error\n", fd);
+ return -1;
+ }
+
+ if (0 != mtd_get_info(fd, &meminfo))
+ {
+ printf("[libmtd]: mtd_erase_offset, get fd(%d) info error, %s\n", fd, strerror(errno));
+ return -1;
+ }
+
+ if (0 != (offset % meminfo.erasesize))
+ {
+ printf("[libmtd]: mtd_erase_offset, not at the beginning of a block, erasesize is %d\n", meminfo.erasesize);
+ return -1;
+ }
+
+ erase_info.length = meminfo.erasesize;
+ erase_info.start = offset;
+
+ if (mtd_block_isbad(fd, erase_info.start))
+ {
+ return -1;
+ }
+ if (0 != ioctl(fd, MEMERASE64, &erase_info))
+ {
+ printf("[libmtd]: mtd_erase_offset, erasing failure at 0x%llx\n", erase_info.start);
+ if (ioctl(fd, MEMSETBADBLOCK, &(erase_info.start)) < 0)
+ {
+ printf("[libmtd]: mtd_erase_offset, mark bad block error, %s\n", strerror(errno));
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+ssize_t mtd_write_offset(int fd, off_t offset, const void *buf, size_t count)
+{
+ ssize_t writen_len;
+ struct mtd_info_user meminfo = {0};
+
+ if (fd < 0)
+ {
+ return -1;
+ }
+
+ if (0 != mtd_get_info(fd, &meminfo))
+ {
+ printf("[libmtd]: mtd_write_offset, get fd(%d) info error, %s\n", fd, strerror(errno));
+ return -1;
+ }
+ if (count <= 0 || count > meminfo.erasesize)
+ {
+ printf("[libmtd]: mtd_write_offset, count(0x%lx), less than 0, or larger than erasesize(0x%x)\n", count, meminfo.erasesize);
+ return -1;
+ }
+ if (0 != (offset % meminfo.erasesize))
+ {
+ printf("[libmtd]: mtd_write_offset, not at the beginning of a block, erasesize is 0x%x\n", meminfo.erasesize);
+ return -1;
+ }
+
+ if (mtd_block_isbad(fd, offset))
+ {
+ return -1;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ {
+ printf("[libmtd]: mtd_write_offset, lseek error = %s!\n", strerror(errno));
+ return -1;
+ }
+ writen_len = writen(fd, buf, count);
+ if (writen_len != count)
+ {
+ if (-1 == writen_len)
+ {
+ printf("[libmtd]: mtd_write_offset, write error, %s\n", strerror(errno));
+ }
+ return -1;
+ }
+
+ return writen_len;
+}
+
+ssize_t mtd_read_offset(int fd, off_t offset, void *buf, size_t count)
+{
+ ssize_t readn_len;
+ struct mtd_info_user meminfo = {0};
+
+ if (fd < 0)
+ {
+ return -1;
+ }
+
+ if (0 != mtd_get_info(fd, &meminfo))
+ {
+ printf("[libmtd]: mtd_read_offset, get fd(%d) info error, %s\n", fd, strerror(errno));
+ return -1;
+ }
+ if (count <= 0 || count > meminfo.erasesize)
+ {
+ printf("[libmtd]: mtd_read_offset, count(0x%lx), less than 0, or larger than erasesize(0x%x)\n", count, meminfo.erasesize);
+ return -1;
+ }
+ if (0 != (offset % meminfo.erasesize))
+ {
+ printf("[libmtd]: mtd_read_offset, not at the beginning of a block, erasesize is %x\n", meminfo.erasesize);
+ return -1;
+ }
+
+ if (mtd_block_isbad(fd, offset))
+ {
+ return -1;
+ }
+
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ {
+ printf("[libmtd]: mtd_read_offset, lseek error = %s!\n", strerror(errno));
+ return -1;
+ }
+ readn_len = readn(fd, buf, count);
+ if (readn_len != count)
+ {
+ if (-1 == readn_len)
+ {
+ printf("[libmtd]: mtd_read_offset, read error, %s\n", strerror(errno));
+ }
+ return -1;
+ }
+
+ return readn_len;
+}
+
+static int zftl_verify_partition(const char *partition_name, const char *image_file)
+{
+ int ret = 0;
+ ssize_t rd_len;
+ size_t read_size = 4096;
+ char zftl_path[MTD_PATH_LENGTH_MAX] = {0};
+ int fd_zftl = -1;
+ struct mtd_info_user meminfo = {0};
+
+ off_t data_size = 0;
+ off_t index = 0;
+ off_t fd_img_index = 0;
+ int fd_img = -1;
+ char *buf = NULL;
+ char *buf2 = NULL;
+ struct stat statbuff = {0};
+
+ if (NULL == partition_name || NULL == image_file)
+ {
+ return -1;
+ }
+
+ ret = mtd_find(partition_name, DEVICE_ZFTL, zftl_path, MTD_PATH_LENGTH_MAX);
+ if (ret < 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, mtd_find %s failed\n", partition_name);
+ return -1;
+ }
+ fd_zftl = open(zftl_path, O_RDONLY);
+ if (fd_zftl < 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, open %s error, %s\n", partition_name, strerror(errno));
+ return -1;
+ }
+
+ if (stat(image_file, &statbuff) < 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, stat %s failed, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ fd_img = open(image_file, O_RDONLY);
+ if (fd_img < 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, open %s failed, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ buf = (char *)malloc(read_size);
+ if (!buf)
+ {
+ printf("[libmtd]: zftl_verify_partition, malloc failed\n");
+ ret = -1;
+ goto out;
+ }
+ buf2 = (char *)malloc(read_size);
+ if (!buf2)
+ {
+ printf("[libmtd]: zftl_verify_partition, malloc2 failed\n");
+ ret = -1;
+ goto out;
+ }
+
+ for (index = 0; fd_img_index < statbuff.st_size; index += read_size)
+ {
+ //memset(buf, 0xFF, read_size);
+
+ if (fd_img_index + read_size > statbuff.st_size)
+ {
+ data_size = statbuff.st_size - fd_img_index;
+ }
+ else
+ {
+ data_size = read_size;
+ }
+ // data_size = (fd_img_index + read_size > statbuff.st_size) ? (statbuff.st_size - fd_img_index) : (read_size);
+
+ rd_len = readn(fd_img, buf, (size_t)data_size);
+ if (rd_len < 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, read image file %s error, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ fd_img_index += data_size;
+
+ rd_len = readn(fd_zftl, buf2, (size_t)data_size);
+ if (rd_len < 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, read zftl %s error, %s\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ if (memcmp(buf, buf2, (size_t)data_size) != 0)
+ {
+ printf("[libmtd]: zftl_verify_partition, data memcmp %s error\n", partition_name);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ ret = 0;
+out:
+ if (fd_zftl >= 0)
+ {
+ //fsync(fd_zftl);
+ close(fd_zftl);
+ }
+
+ if (buf != NULL)
+ {
+ // memset(buf, 0xFF, meminfo.erasesize);
+ free(buf);
+ }
+ if (buf2 != NULL)
+ {
+ // memset(buf, 0xFF, meminfo.erasesize);
+ free(buf2);
+ }
+
+ if (fd_img >= 0)
+ {
+ close(fd_img);
+ }
+ if (ret == 0)
+ {
+ printf("[libmtd]: zftl %s verify sucess\n", partition_name);
+ }
+ else
+ {
+ printf("[libmtd]: zftl %s verify fail\n", partition_name);
+ }
+
+ return ret;
+}
+
+int zftl_write_partition(const char *partition_name, const char *image_file)
+{
+ int ret = 0;
+ ssize_t wr_len;
+ size_t write_size = 4096;
+ char zftl_path[MTD_PATH_LENGTH_MAX] = {0};
+ int fd_zftl = -1;
+ struct mtd_info_user meminfo = {0};
+
+ off_t data_size = 0;
+ off_t index = 0;
+ off_t fd_img_index = 0;
+ int fd_img = -1;
+ char *buf = NULL;
+ struct stat statbuff = {0};
+
+ if (NULL == partition_name || NULL == image_file)
+ {
+ return -1;
+ }
+
+ ret = mtd_find(partition_name, DEVICE_ZFTL, zftl_path, MTD_PATH_LENGTH_MAX);
+ if (ret < 0)
+ {
+ printf("[libmtd]: zftl_write_partition, mtd_find %s failed\n", partition_name);
+ return -1;
+ }
+ fd_zftl = open(zftl_path, O_RDWR);
+ if (fd_zftl < 0)
+ {
+ printf("[libmtd]: zftl_write_partition, open %s error, %s\n", partition_name, strerror(errno));
+ return -1;
+ }
+
+ if (stat(image_file, &statbuff) < 0)
+ {
+ printf("[libmtd]: zftl_write_partition, stat %s failed, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ fd_img = open(image_file, O_RDONLY);
+ if (fd_img < 0)
+ {
+ printf("[libmtd]: zftl_write_partition, open %s failed, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ buf = (char *)malloc(write_size);
+ if (!buf)
+ {
+ printf("[libmtd]: zftl_write_partition, malloc failed\n");
+ ret = -1;
+ goto out;
+ }
+
+ for (index = 0; fd_img_index < statbuff.st_size; index += write_size)
+ {
+ memset(buf, 0xFF, write_size);
+
+ if (fd_img_index + write_size > statbuff.st_size)
+ {
+ data_size = statbuff.st_size - fd_img_index;
+ }
+ else
+ {
+ data_size = write_size;
+ }
+ // data_size = (fd_img_index + write_size > statbuff.st_size) ? (statbuff.st_size - fd_img_index) : (write_size);
+
+ wr_len = readn(fd_img, buf, (size_t)data_size);
+ if (wr_len < 0)
+ {
+ printf("[libmtd]: zftl_write_partition, read %s error, %s\n", image_file, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+ fd_img_index += data_size;
+
+ wr_len = writen(fd_zftl, buf, (size_t)data_size);
+ if (wr_len < 0)
+ {
+ printf("[libmtd]: zftl_write_partition, write %s error, %s\n", partition_name, strerror(errno));
+ ret = -1;
+ goto out;
+ }
+
+ }
+ if (fd_img_index < statbuff.st_size)
+ {
+ printf("[libmtd]: zftl_write_partition, No space left, writelen=0x%lx, filesize=0x%lx\n", fd_img_index, statbuff.st_size);
+ ret = -1;
+ goto out;
+ }
+ ret = 0;
+out:
+ if (fd_zftl >= 0)
+ {
+ fsync(fd_zftl);
+ close(fd_zftl);
+ }
+
+ if (buf != NULL)
+ {
+ // memset(buf, 0xFF, meminfo.erasesize);
+ free(buf);
+ }
+
+ if (fd_img >= 0)
+ {
+ close(fd_img);
+ }
+
+ if (ret == 0)
+ {
+ //write sucess then do verify
+ ret = zftl_verify_partition(partition_name, image_file);
+ }
+
+ return ret;
+}
\ No newline at end of file