#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; | |
} | |