| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <fcntl.h> | |
| #include <unistd.h> | |
| #include <sys/ioctl.h> | |
| #include <mtd/mtd-user.h> | |
| #include <errno.h> | |
| #include <dlfcn.h> | |
| #include "mbtk_log.h" | |
| #define FLASH_DEVICE "/dev/mtd32" | |
| #define BACKUP_DEVICE "/dev/mtd33" | |
| /** | |
| * @brief 从指定的flash页面读取数据 | |
| * @param block_id 块ID(从1开始) | |
| * @param data 存储读取数据的缓冲区 | |
| * @param len 存储读取数据长度的指针 | |
| * @return GSW_HAL_SUCCESS 或 GSW_HAL_FAIL | |
| */ | |
| int mbtk_oem_read_data_ext(unsigned int block_id, void *data, unsigned int *len) | |
| { | |
| int fd; | |
| struct mtd_info_user mtd_info; | |
| off_t offset; | |
| ssize_t bytes_read; | |
| unsigned int max_block_id; | |
| // 输入参数验证 | |
| if (!data || !len) | |
| { | |
| LOGE("invalid :data or len is NULL\n"); | |
| return -2; | |
| } | |
| // 打开flash设备 | |
| fd = open(FLASH_DEVICE, O_RDONLY); | |
| if (fd == -1) | |
| { | |
| LOGE("open flash device error %s\n", strerror(errno)); | |
| return -1; | |
| } | |
| // 获取MTD设备信息 | |
| if (ioctl(fd, MEMGETINFO, &mtd_info) < 0) | |
| { | |
| LOGE("Get MTD info erro:%s\n", strerror(errno)); | |
| close(fd); | |
| return -1; | |
| } | |
| // 计算最大块ID | |
| max_block_id = mtd_info.size / mtd_info.erasesize; | |
| // 验证block_id | |
| if (block_id < 1 || block_id > max_block_id) | |
| { | |
| LOGE("invalid block_id: %u (max: %u)\n", block_id, max_block_id); | |
| close(fd); | |
| return -2; | |
| } | |
| // 计算偏移量(block_id从1开始) | |
| offset = (block_id - 1) * mtd_info.erasesize; | |
| // 定位到块位置 | |
| if (lseek(fd, offset, SEEK_SET) == -1) | |
| { | |
| LOGE("lseek block error:%s\n", strerror(errno)); | |
| close(fd); | |
| return -1; | |
| } | |
| // 读取块 | |
| bytes_read = read(fd, data, mtd_info.erasesize); | |
| if (bytes_read != mtd_info.erasesize) | |
| { | |
| LOGE("Read block fail:%s\n", strerror(errno)); | |
| close(fd); | |
| return -1; | |
| } | |
| *len = bytes_read; | |
| close(fd); | |
| return 0; | |
| } | |
| /** | |
| * @brief 向指定的flash页面写入数据并进行备份 | |
| * @param block_id 块ID(从1开始) | |
| * @param data 要写入的数据 | |
| * @param len 要写入的数据长度 | |
| * @return GSW_HAL_SUCCESS 或 GSW_HAL_FAIL | |
| */ | |
| int mbtk_oem_write_data_ext(unsigned int block_id, void *data, unsigned int len) | |
| { | |
| int fd_main; | |
| int fd_backup; | |
| struct mtd_info_user mtd_info; | |
| off_t offset_main; | |
| off_t offset_backup; | |
| ssize_t bytes_written; | |
| unsigned int max_block_id; | |
| struct erase_info_user erase_info; | |
| // 输入参数验证 | |
| if (!data) | |
| { | |
| printf("invalid data is NULL\n"); | |
| return -2; | |
| } | |
| // 首先打开主设备以获取MTD信息 | |
| fd_main = open(FLASH_DEVICE, O_RDWR); | |
| if (fd_main == -1) | |
| { | |
| printf("open flash error %s\n", strerror(errno)); | |
| return -1; | |
| } | |
| // 获取MTD设备信息 | |
| if (ioctl(fd_main, MEMGETINFO, &mtd_info) < 0) | |
| { | |
| printf("get mtd block info error %s\n", strerror(errno)); | |
| close(fd_main); | |
| return -1; | |
| } | |
| // 计算最大块ID | |
| max_block_id = mtd_info.size / mtd_info.erasesize; | |
| // 验证block_id和len | |
| if (block_id < 1 || block_id > max_block_id) | |
| { | |
| LOGE("invalid block_id: %u (max:%u)\n", block_id, max_block_id); | |
| close(fd_main); | |
| return -2; | |
| } | |
| if (len > mtd_info.erasesize) | |
| { | |
| LOGE("invalid len: %u (max: %u)\n", len, mtd_info.erasesize); | |
| close(fd_main); | |
| return -2; | |
| } | |
| // 打开备份设备 | |
| fd_backup = open(BACKUP_DEVICE, O_RDWR); | |
| if (fd_backup == -1) | |
| { | |
| LOGE("open bak device fail %s\n", strerror(errno)); | |
| close(fd_main); | |
| return -1; | |
| } | |
| // 计算偏移量 | |
| offset_main = (block_id - 1) * mtd_info.erasesize; | |
| offset_backup = (block_id - 1) * mtd_info.erasesize; | |
| // 准备erase_info结构体 | |
| erase_info.start = offset_main; // 设置主设备的起始位置 | |
| erase_info.length = mtd_info.erasesize; // 设置擦除长度 | |
| // 首先写入备份 | |
| if (ioctl(fd_backup, MEMERASE, &erase_info) < 0) | |
| { | |
| LOGE("MEMERASE backup block faile:%s\n", strerror(errno)); | |
| close(fd_main); | |
| close(fd_backup); | |
| return -1; | |
| } | |
| if (lseek(fd_backup, offset_backup, SEEK_SET) == -1) | |
| { | |
| LOGE("lseek backup device failed %s\n", strerror(errno)); | |
| close(fd_main); | |
| close(fd_backup); | |
| return -1; | |
| } | |
| bytes_written = write(fd_backup, data, len); | |
| if (bytes_written != len) | |
| { | |
| LOGE("write to backup flahs failed %s\n", strerror(errno)); | |
| close(fd_main); | |
| close(fd_backup); | |
| return -1; | |
| } | |
| erase_info.start = offset_main; | |
| erase_info.length = mtd_info.erasesize; | |
| // 然后写入主flash | |
| if (ioctl(fd_main, MEMERASE, &erase_info) < 0) | |
| { | |
| LOGE("MEMERASE main flash failed %s\n", strerror(errno)); | |
| close(fd_main); | |
| close(fd_backup); | |
| return -1; | |
| } | |
| if (lseek(fd_main, offset_main, SEEK_SET) == -1) | |
| { | |
| LOGE("lseek main flash failed %s\n", strerror(errno)); | |
| close(fd_main); | |
| close(fd_backup); | |
| return -1; | |
| } | |
| bytes_written = write(fd_main, data, len); | |
| if (bytes_written != len) | |
| { | |
| LOGE(" write to main flash failed %s\n", strerror(errno)); | |
| close(fd_main); | |
| close(fd_backup); | |
| return -1; | |
| } | |
| // 确保数据已写入flash | |
| fsync(fd_main); | |
| fsync(fd_backup); | |
| close(fd_main); | |
| close(fd_backup); | |
| return 0; | |
| } | |