| #define _GNU_SOURCE |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <sys/vfs.h> |
| |
| |
| #include <mtd/mtd-abi.h> |
| #include <errno.h> |
| |
| #include <sys/ioctl.h> |
| #include "mtd.h" |
| |
| |
| int mtd_find(const char *i_parti_name, char *o_mtd_path, device_type_t device_type, unsigned int o_mtd_path_len) |
| { |
| FILE *fd_mtd = 0; |
| char buf[128]; |
| char *line_str; |
| |
| if (!o_mtd_path_len) |
| return -1; |
| |
| fd_mtd = fopen("/proc/mtd", "r+"); |
| if (NULL == fd_mtd) { |
| printf("fs_check open file error:%s", strerror(errno)); |
| //sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check open file error:%s", strerror(errno)); |
| goto error0; |
| } |
| //printf("fs_check 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, 0x00, sizeof(buf)); |
| line_str = fgets(buf, sizeof(buf), fd_mtd); |
| |
| if (NULL == line_str) { |
| printf("fs_check get info from mtd error:%s\n", strerror(errno)); |
| //sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check get info from mtd error:%s\n", strerror(errno)); |
| goto error1; |
| } |
| //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, 0x00, 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("fs_check unknown device type %d\n", device_type); |
| //sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check unknown device type %d\n", device_type); |
| goto error1; |
| } |
| //printf("fs_check o_mtd_path=[%s]\n", o_mtd_path); |
| break; |
| } |
| |
| } |
| fclose(fd_mtd); |
| return 0; |
| |
| error1: |
| fclose(fd_mtd); |
| error0: |
| return -1; |
| } |
| |
| int mtd_erase_partition(const char* partition_name) |
| { |
| int ret = 0; |
| char mtd_path[MAX_PATH] = {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, mtd_path, DEVICE_MTD, MAX_PATH); |
| if (ret < 0) { |
| printf("fs_check mtd_find %s failed\n", partition_name); |
| //sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check mtd_find %s failed\n", partition_name); |
| ret = -1; |
| goto out; |
| } |
| fd_mtd = open(mtd_path, O_RDWR); |
| if (fd_mtd < 0) { |
| printf("fs_check open %s error, %s\n", partition_name, strerror(errno)); |
| //sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check open %s error, %s\n", partition_name, strerror(errno)); |
| ret = -1; |
| goto out; |
| } |
| if (ioctl(fd_mtd, MEMGETINFO, &meminfo) != 0) { |
| printf("fs_check get %s info error, %s\n", partition_name, strerror(errno)); |
| //sc_debug_info_record(MODULE_ID_AP_FS_CHECK, "fs_check 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) { |
| if (ioctl(fd_mtd, MEMGETBADBLOCK, &(erase_info.start)) > 0) { |
| printf("fs_check mtd, not erasing bad block at 0x%llx\n", erase_info.start); |
| continue; |
| } |
| if (ioctl(fd_mtd, MEMERASE64, &erase_info) < 0) { |
| printf("fs_check mtd, erasing failure at 0x%llx\n", erase_info.start); |
| } |
| } |
| ret = 0; |
| out: |
| if (fd_mtd >= 0) { |
| close(fd_mtd); |
| } |
| return ret; |
| } |