解析以下文件:
#include <sys/ioctl.h> /* for ioctl() */
#include <fcntl.h> /* for O_RDONLY */
#include <unistd.h> /* for close() */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <malloc.h>
#include <arpa/inet.h>
#include "flashio_name_path.h"
#include "rax.h"
#include "nvmp_utils.h" /* for NSD_DEBUG() */
#include "flashio.h"
static rax *rax_ctx = NULL;
static TP_HEAD_INFO *pt_header = NULL;
#define UC_PART_PATH "/tmp/uc_file/UC"
//通用接口返回当前分区有效数据大小,但是分区数据用文件系统存储的禁止用次接口获取(例如在ubifs中存储uc)
int get_pt_table_size_general(char *name)
{
int pt_size = 0;
pt_usr_table *pt_utb = NULL;
char mtd_type = 0;
if (rax_ctx == NULL || pt_header == NULL)
return FLASH_INIT_ERROR;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if (pt_utb == raxNotFound)
{
FLASHIO_ERROR("not found %s",name);
return FLASH_NOT_EXIT;
}
if (pt_utb->pt_table != NULL)
mtd_type = GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->pt_table->partition_attribute);
else if (pt_utb->vol_table != NULL)
mtd_type = GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->vol_table->partition_attribute);
else
return FLASH_NORMAL;
switch (mtd_type)
{
case PARTITION_ITEM_TYPE_MTD:
pt_size = pt_utb->pt_table->valid_size;
break;
case PARTITION_ITEM_TYPE_UBI:
pt_size = pt_utb->vol_table->valid_size;
break;
}
return pt_size;
}
//通用接口返回当前分区有效长度大小,但是分区数据用文件系统存储的禁止用次接口获取(例如在ubifs中存储uc)
int get_pt_table_all_size_general(char *name)
{
int pt_size = 0;
pt_usr_table *pt_utb = NULL;
char mtd_type = 0;
if (rax_ctx == NULL || pt_header == NULL)
return 0;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if (pt_utb == raxNotFound)
{
FLASHIO_ERROR("not found %s",name);
return FLASH_INIT_ERROR;
}
if (pt_utb->pt_table != NULL)
mtd_type = GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->pt_table->partition_attribute);
else if (pt_utb->vol_table != NULL)
mtd_type = GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->vol_table->partition_attribute);
else
return FLASH_NORMAL;
switch (mtd_type)
{
case PARTITION_ITEM_TYPE_MTD:
pt_size = pt_utb->pt_table->partition_valid_size;
break;
case PARTITION_ITEM_TYPE_UBI:
pt_size = pt_utb->vol_table->vol_valid_size;
break;
}
return pt_size;
}
//通用接口返回当前分区大小,但是分区数据用文件系统存储的禁止用次接口获取(例如在ubifs中存储uc)
int get_pt_table_all_length_general(char *name)
{
int pt_size = 0;
pt_usr_table *pt_utb = NULL;
char mtd_type = 0;
if (rax_ctx == NULL || pt_header == NULL)
return FLASH_INIT_ERROR;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if (pt_utb == raxNotFound)
{
FLASHIO_ERROR("not found %s",name);
return FLASH_NOT_EXIT;
}
if (pt_utb->pt_table != NULL)
mtd_type = GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->pt_table->partition_attribute);
else if (pt_utb->vol_table != NULL)
mtd_type = GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->vol_table->partition_attribute);
else
return 0;
switch (mtd_type)
{
case PARTITION_ITEM_TYPE_MTD:
pt_size = pt_utb->pt_table->partition_length;
break;
case PARTITION_ITEM_TYPE_UBI:
pt_size = pt_utb->vol_table->vol_size;
break;
}
return pt_size;
}
//通用接口返回当前分区偏移值,但是分区数据用文件系统存储的禁止用次接口获取(例如在ubifs中存储uc)
int get_pt_table_offset_general(char *name)
{
int pt_offset = 0;
pt_usr_table *pt_utb = NULL;
if (rax_ctx == NULL || pt_header == NULL)
return FLASH_INIT_ERROR;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if (pt_utb == raxNotFound)
{
FLASHIO_ERROR("not found %s",name);
return FLASH_NOT_EXIT;
}
switch (GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->pt_table->partition_attribute))
{
case PARTITION_ITEM_TYPE_MTD:
pt_offset = pt_utb->pt_table->partition_offset;
break;
case PARTITION_ITEM_TYPE_UBI:
pt_offset = 0;
}
return pt_offset;
}
//通用接口读取当前flash数据
int read_flash_pt_data_general(void *arg_index,char *filename)
{
int fd = 0,ret = FLASH_IO_ERROR;
ARG *arg = (ARG *)arg_index;
pt_usr_table *pt_utb = NULL;
if (filename)
{
fd = open(filename,O_RDONLY,0666);
if (fd <= 0)
{
FLASHIO_ERROR("not open %s",filename);
goto exit;
}
ret = read(fd,arg->rw_buf,arg->length);
if (ret != arg->length)
{
FLASHIO_ERROR("read %d is not equal %d",arg->length,ret);
goto exit;
}
ret = FLASH_NORMAL;
}
else
{
if (rax_ctx == NULL || pt_header == NULL)
return FLASH_INIT_ERROR;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)arg->pt_name,strlen(arg->pt_name));
if (pt_utb == raxNotFound)
goto exit;
fd = open(FLASH_DEV,O_RDONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
goto exit;
}
arg->mtd_info = pt_utb->mtd_info;
FLASHIO_INFO("will read %s 0x%x 0x%x",arg->pt_name,arg->offset,arg->length);
ret = ioctl(fd,SLP_IOC_FLASH_READ,arg);
if (ret)
goto exit;
ret = FLASH_NORMAL;
}
exit:
if (fd > 0)
close(fd);
return ret;
}
//通用接口写入flash数据(新接口不进行擦除,调用需要先进行擦除)
int write_pt_table_data_general(ARG *arg,char *file_name,char force_flag)
{
int fd = 0,ret = 0;
if (file_name)
{
//清空文件
fd = open(file_name,O_CREAT | O_RDWR | O_SYNC,0666);
if (fd <= 0)
{
FLASHIO_ERROR("pt %s is renew",file_name);
ret = FLASH_IO_ERROR;
goto exit;
}
ret = lseek(fd,arg->offset,SEEK_SET);
if (ret != arg->offset)
goto exit;
ret = write(fd,arg->rw_buf,arg->length);
if (ret != arg->length)
goto exit;
fsync(fd);
}
else
{
if (rax_ctx == NULL || pt_header == NULL)
return FLASH_INIT_ERROR;
pt_usr_table *pt_utb = NULL;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)arg->pt_name,strlen(arg->pt_name));
if (pt_utb == raxNotFound)
goto exit;
if (force_flag == 0 &&
((pt_utb->vol_table != NULL && GET_PARTITION_ATTRIBUTE(DATA_FORBID,pt_utb->vol_table->partition_attribute)) ||
(pt_utb->pt_table != NULL && GET_PARTITION_ATTRIBUTE(DATA_FORBID,pt_utb->pt_table->partition_attribute))))
{
FLASHIO_ERROR("the partition is forbid change");
return -1;
}
fd = open(FLASH_DEV,O_WRONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
ret = FLASH_IO_ERROR;
goto exit;
}
arg->mtd_info = pt_utb->mtd_info;
FLASHIO_INFO("will write %s 0x%x 0x%x",arg->pt_name,arg->offset,arg->length);
ret = ioctl(fd,SLP_IOC_FLASH_WRITE,arg);
if (ret)
{
FLASHIO_ERROR("write %s error",arg->pt_name);
goto exit;
}
}
ret = 0;
exit:
if (fd > 0)
close(fd);
return ret;
}
/* 通用接口擦除flash
* note:nand可能有坏块,此时ubi格式化不能使用全长度,需要把坏块去除,引入最小长度参数保证能写入镜像
* 不依赖ubiformat格式化,因为ubiformat会使用scan测试块,此时可能会因为写入过垃圾数据失败
*/
int erase_pt_table_data_general(ARG *arg,char *file_name,char force_flag,int min_erase_block)
{
int fd = 0,ret = 0;
if (arg == NULL)
return FLASH_IO_ERROR;
if (file_name)
{
//清空文件
int byte = 0;
char space = 0xff;
if (arg->length == 0)
{
//全文件清空
fd = open(file_name,O_CREAT | O_RDWR | O_TRUNC,0666);
if (fd <= 0)
{
FLASHIO_ERROR("pt %s is renew",file_name);
ret = FLASH_IO_ERROR;
goto exit;
}
}
else
{
//模拟flash
fd = open(file_name,O_CREAT | O_RDWR,0666);
if (fd <= 0)
{
FLASHIO_ERROR("pt %s is renew",file_name);
ret = FLASH_IO_ERROR;
goto exit;
}
ret = lseek(fd,arg->offset,SEEK_SET);
if (ret != arg->offset)
goto exit;
for (byte = 0;byte < arg->length;byte++)
write(fd,&space,1);
fsync(fd);
}
}
else
{
pt_usr_table *pt_utb = NULL;
if (rax_ctx == NULL || pt_header == NULL)
return -1;
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)arg->pt_name,strlen(arg->pt_name));
if (pt_utb == raxNotFound)
goto exit;
if (force_flag == 0 &&
((pt_utb->vol_table != NULL && GET_PARTITION_ATTRIBUTE(DATA_FORBID,pt_utb->vol_table->partition_attribute)) ||
(pt_utb->pt_table != NULL && GET_PARTITION_ATTRIBUTE(DATA_FORBID,pt_utb->pt_table->partition_attribute))))
{
FLASHIO_ERROR("the partition is forbid change");
return FLASH_IO_ERROR;
}
fd = open(FLASH_DEV,O_WRONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
ret = FLASH_IO_ERROR;
goto exit;
}
arg->mtd_info = pt_utb->mtd_info;
arg->min_erase_block = min_erase_block;
FLASHIO_INFO("will erase %s 0x%x 0x%x(0x%x)",arg->pt_name,arg->offset,arg->length,min_erase_block);
ret = ioctl(fd,SLP_IOC_FLASH_ERASE,arg);
if (ret)
{
FLASHIO_ERROR("not erase flash %s",arg->pt_name);
goto exit;
}
}
ret = 0;
exit:
if (fd > 0)
close(fd);
return ret;
}
void *get_tp_header_ctx()
{
return pt_header;
}
void* find_pt_table_from_tpheader(TP_HEAD_INFO *tpheader,char *pt_name)
{
partition_table_item *pt_table = NULL;
int partition_id = 0;
if (tpheader == NULL)
return NULL;
for (partition_id = 0;partition_id < tpheader->partition_num;partition_id++)
{
pt_table = &(tpheader->table[partition_id]);
if (strcmp(pt_table->partition_name,pt_name) == 0)
break;
}
if (partition_id == tpheader->partition_num)
pt_table = NULL;
return pt_table;
}
void* find_vol_table_from_pt_table(partition_table_item *pt_table,char *vol_name)
{
ubi_vol *vol = NULL;
int vol_id = 0;
if (pt_table == NULL)
return NULL;
for (vol_id = 0;vol_id < UBI_MAX_NUM;vol_id++)
{
vol = &(pt_table->vol_table[vol_id]);
if (strcmp(vol->vol_name,vol_name) == 0)
break;
}
if (vol_id == UBI_MAX_NUM)
vol = NULL;
return vol;
}
void *get_flash_partition_from_radix(char *name)
{
return raxFind(rax_ctx,(unsigned char *)name,strlen(name));
}
static int init_pt_table()
{
int fd = 0,ret = 0;
ARG arg = {0};
if (pt_header != NULL)
free(pt_header);
pt_header = malloc(sizeof(TP_HEAD_INFO));
if (pt_header == NULL)
return FLASH_INIT_ERROR;
fd = open(FLASH_DEV,O_RDONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
ret = FLASH_INIT_ERROR;
goto exit;
}
strcpy(arg.pt_name,"pt_table");
ret = ioctl(fd,SLP_IOC_FLASH_GET_INFO,&arg);
if (ret)
{
FLASHIO_ERROR("not found pt_table");
goto exit;
}
arg.offset = 0;
arg.rw_buf = (unsigned char *)pt_header;
arg.length = sizeof(TP_HEAD_INFO);
ret = ioctl(fd,SLP_IOC_FLASH_READ,&arg);
if (ret)
goto exit;
pt_header = realloc(pt_header,sizeof(TP_HEAD_INFO) + sizeof(partition_table_item) * ntohs(pt_header->partition_num));
if (pt_header == NULL)
goto exit;
arg.offset = 0;
arg.rw_buf = (unsigned char *)pt_header;
arg.length = sizeof(TP_HEAD_INFO) + sizeof(partition_table_item) * ntohs(pt_header->partition_num);
ret = ioctl(fd,SLP_IOC_FLASH_READ,&arg);
switch_partition_table_to_local(pt_header);
if (ret || pt_header->partition_num > 32)
{
ret = FLASH_INIT_ERROR;
goto exit;
}
FLASHIO_INFO("pt_tabel is init finish");
//factory启动阶段已保证分区数据可靠性,此处不在校验
close(fd);
return 0;
exit:
if (pt_header)
{
free(pt_header);
pt_header = NULL;
}
if(fd > 0)
close(fd);
return ret;
}
static int add_radix_node(pt_usr_table *utb,char *name)
{
pt_usr_table *pt_utb = NULL;
int ret = 0;
pt_utb = calloc(sizeof(pt_usr_table),1);
if (pt_utb == NULL)
{
ret = FLASH_INIT_ERROR;
goto exit;
}
memcpy(pt_utb,utb,sizeof(pt_usr_table));
ret = raxInsert(rax_ctx,(unsigned char *)name,strlen(name),pt_utb,NULL);
if (ret == 1)
ret = 0;
FLASHIO_DEBUG("create %s node finish code %d",name,ret);
exit:
if (pt_utb && ret != 0)
free(pt_utb);
return ret;
}
static void destroy_radix_node(char *name)
{
pt_usr_table *pt_utb = raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if (pt_utb == raxNotFound)
return;
raxRemove(rax_ctx,(unsigned char *)name,strlen(name),NULL);
if (pt_utb->free_flag && pt_utb->pt_table)
free(pt_utb->pt_table);
if (pt_utb->free_flag && pt_utb->vol_table)
free(pt_utb->vol_table);
free(pt_utb);
FLASHIO_DEBUG("delete %s node finish\n",name);
}
static void destroy_all_radix_node()
{
raxIterator rax_it = {0};
pt_usr_table *pt_utb = NULL;
raxStart(&rax_it,rax_ctx);
raxSeek(&rax_it,"^",NULL,0);
while (raxNext(&rax_it) != 0)
{
pt_utb = (pt_usr_table *)rax_it.data;
if (pt_utb->free_flag && pt_utb->pt_table)
free(pt_utb->pt_table);
else if (pt_utb->free_flag && pt_utb->vol_table)
free(pt_utb->pt_table);
}
raxStop(&rax_it);
raxFree(rax_ctx);
rax_ctx = NULL;
FLASHIO_INFO("destroy all node,flash module is not use");
}
static int create_pt_usr_manager()
{
partition_table_item *table = NULL;
ubi_vol *vol_table = NULL;
ARG arg = {0};
pt_usr_table pt_utb = {0};
int ret = 0,fd = 0;
short pt_id = 0,vol_id = 0;
fd = open(FLASH_DEV,O_RDONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
ret = -1;
goto exit;
}
for (pt_id = 0;pt_id < pt_header->partition_num;pt_id++)
{
table = &(pt_header->table[pt_id]);
if (table->partition_length == 0)
continue;
switch (GET_PARTITION_ATTRIBUTE(FLASH_TYPE,table->partition_attribute))
{
case PARTITION_ITEM_TYPE_MTD:
strcpy(arg.pt_name,table->partition_name);
ret = ioctl(fd,SLP_IOC_FLASH_GET_INFO,&arg);
if (ret)
{
FLASHIO_ERROR("not found %s",table->partition_name);
goto exit;
}
pt_utb.pt_table = table;
pt_utb.mtd_info = arg.mtd_info;
pt_utb.free_flag = 0;
pt_utb.mtd_id = arg.mtd_id;
pt_utb.vol_table = NULL;
ret = add_radix_node(&pt_utb,table->partition_name);
if (ret)
goto exit;
break;
case PARTITION_ITEM_TYPE_UBI:
for (vol_id = 0;vol_id < UBI_MAX_NUM;vol_id++)
{
vol_table = &(table->vol_table[vol_id]);
if (strlen(vol_table->vol_name) == 0)
continue;
strcpy(arg.pt_name,vol_table->vol_name);
ret = ioctl(fd,SLP_IOC_FLASH_GET_INFO,&arg);
if (ret)
{
FLASHIO_ERROR("not found %s",vol_table->vol_name);
goto exit;
}
pt_utb.vol_table = vol_table;
pt_utb.mtd_info = arg.mtd_info;
pt_utb.free_flag = 0;
pt_utb.mtd_id = arg.mtd_id;
pt_utb.ubi_id = arg.ubi_id;
pt_utb.pt_table = NULL;
ret = add_radix_node(&pt_utb,arg.pt_name);
if (ret)
goto exit;
}
strcpy(arg.pt_name,table->partition_name);
ret = ioctl(fd,SLP_IOC_FLASH_GET_INFO,&arg);
if (ret)
{
FLASHIO_ERROR("not found %s",table->partition_name);
goto exit;
}
pt_utb.pt_table = table;
pt_utb.mtd_info = arg.mtd_info;
pt_utb.free_flag = 0;
pt_utb.mtd_id = arg.mtd_id;
pt_utb.vol_table = NULL;
ret = add_radix_node(&pt_utb,table->partition_name);
if (ret)
goto exit;
break;
default:
ret = FLASH_INIT_ERROR;
FLASHIO_ERROR("not known mtd %s type %x",table->partition_name,table->partition_attribute);
goto exit;
}
}
close(fd);
FLASHIO_INFO("create all radix node finish\n");
return 0;
exit:
if (fd > 0)
close(fd);
destroy_all_radix_node();
return ret;
}
static int init_flash_io()
{
int ret = 0;
rax_ctx = raxNew();
if (rax_ctx == NULL)
{
FLASHIO_ERROR("rax is not create");
goto exit;
}
ret = init_pt_table();
if (ret)
goto exit;
ret = create_pt_usr_manager();
if (ret)
goto exit;
flashio_test_register_handler();
FLASHIO_INFO("flash io module init finish\n");
return 0;
exit:
if (rax_ctx)
{
raxFree(rax_ctx);
rax_ctx = NULL;
}
if (pt_header)
{
free(pt_header);
pt_header = NULL;
}
FLASHIO_INFO("init flash module failed");
exit(EXIT_FAILURE);
}
void print_pt_table_debug(void)
{
raxIterator rax_it = {0};
pt_usr_table *pt_utb = NULL;
if (rax_ctx == NULL)
return;
raxStart(&rax_it,rax_ctx);
raxSeek(&rax_it,"^",NULL,0);
printf("%-32s%-16s%-16s%-16s%-16s%-16s%-16s\n","pt_table_name","mtd_type","start","end","forbid","check","deled");
while (raxNext(&rax_it) != 0)
{
pt_utb = (pt_usr_table *)rax_it.data;
if (pt_utb->pt_table)
{
printf("%-32s0x%-14x0x%-14x0x%-14x",pt_utb->pt_table->partition_name,GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->pt_table->partition_attribute),pt_utb->pt_table->partition_offset,pt_utb->pt_table->partition_offset + pt_utb->pt_table->partition_length);
printf("0x%-14x0x%-14x0x%-14x\n",GET_PARTITION_ATTRIBUTE(DATA_FORBID,pt_utb->pt_table->partition_attribute),GET_PARTITION_ATTRIBUTE(DATA_CHECK,pt_utb->pt_table->partition_attribute),GET_PARTITION_ATTRIBUTE(DATA_DEL,pt_utb->pt_table->partition_attribute));
}
else if (pt_utb->vol_table)
{
printf("%-32s0x%-14x0x%-14x0x%-14x",pt_utb->vol_table->vol_name,GET_PARTITION_ATTRIBUTE(FLASH_TYPE,pt_utb->vol_table->partition_attribute),0,pt_utb->vol_table->vol_size);
printf("0x%-14x0x%-14x0x%-14x\n",GET_PARTITION_ATTRIBUTE(DATA_FORBID,pt_utb->vol_table->partition_attribute),GET_PARTITION_ATTRIBUTE(DATA_CHECK,pt_utb->vol_table->partition_attribute),GET_PARTITION_ATTRIBUTE(DATA_DEL,pt_utb->vol_table->partition_attribute));
}
}
raxStop(&rax_it);
}
S32 flash_write_tpheader(U8 *buf, U32 buflen)
{
ARG arg = {0};
int ret = 0;
arg.offset = 0;
arg.length = buflen;
strcpy(arg.pt_name,"pt_table");
arg.rw_buf = buf;
switch_partition_table_to_network((TP_HEAD_INFO *)buf);
ret = write_pt_table_data_general(&arg,NULL,0);
switch_partition_table_to_local((TP_HEAD_INFO *)buf);
return ret;
}
S32 flash_read_tpheader(U8 *buf, U32 buflen)
{
ARG arg = {0};
int ret = 0;
arg.offset = 0;
arg.rw_buf = buf;
arg.length = buflen;
strcpy(arg.pt_name,"pt_table");
ret = read_flash_pt_data_general(&arg,NULL);
if (ret == 0)
switch_partition_table_to_local((TP_HEAD_INFO *)buf);
return ret;
}
U32 get_tpheader_size(void)
{
return get_pt_table_all_size_general("pt_table");
}
S32 flash_read_uc(U8 *buf, U32 buflen, U32 sub_index)
{
ARG arg = {0};
#ifdef USE_NAND_FLASH
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
if (sub_index == 0)
return read_flash_pt_data_general(&arg,UC_USR_CONFIG);
else
return read_flash_pt_data_general(&arg,UC_USR_CONFIG_BAK);
#else
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
if (sub_index == 0)
strcpy(arg.pt_name,PT_UC);
else
strcpy(arg.pt_name,PT_UC_BAK);
return read_flash_pt_data_general(&arg,NULL);
#endif
}
U32 get_uc_size(void)
{
#ifdef USE_NAND_FLASH
return UC_SIZE;
#else
return get_pt_table_all_size_general(PT_UC);
#endif
}
S32 flash_write_uc(U8 *buf, U32 buflen, U32 sub_index)
{
ARG arg = {0};
#ifdef USE_NAND_FLASH
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
if (sub_index == 0)
return write_pt_table_data_general(&arg,UC_USR_CONFIG,0);
else
return write_pt_table_data_general(&arg,UC_USR_CONFIG_BAK,0);
#else
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
if (sub_index == 0)
strcpy(arg.pt_name,PT_UC);
else
strcpy(arg.pt_name,PT_UC_BAK);
return write_pt_table_data_general(&arg,NULL,1);
#endif
}
S32 flash_erase_uc()
{
ARG arg = {0};
arg.offset = 0;
#ifdef USE_NAND_FLASH
arg.length = 0;
int ret = erase_pt_table_data_general(&arg,UC_USR_CONFIG,0,0);
if (ret)
return ret;
ret = erase_pt_table_data_general(&arg,UC_USR_CONFIG_BAK,0,0);
return ret;
#else
strcpy(arg.pt_name,PT_UC);
arg.length = get_uc_size();
return erase_pt_table_data_general(&arg,NULL,1,0);
#endif
}
#ifdef MCU_SUPPORT
S32 flash_read_mcu(U8 *buf,U32 buflen)
{
ARG arg = {0};
arg.offset = 0;
arg.rw_buf = buf;
arg.length = buflen;
strcpy(arg.pt_name,PT_MCU);
return read_flash_pt_data_general(&arg,NULL);
}
#endif
S32 flash_write_radio(U8 *buf, U32 buflen)
{
ARG arg = {0};
arg.offset = 0;
arg.rw_buf = buf;
arg.length = buflen;
strcpy(arg.pt_name,PT_ISP);
return write_pt_table_data_general(&arg,NULL,0);
}
S32 flash_read_radio(U8 *buf, U32 buflen)
{
ARG arg = {0};
arg.offset = 0;
arg.rw_buf = buf;
arg.length = buflen;
strcpy(arg.pt_name,PT_ISP);
return read_flash_pt_data_general(&arg,NULL);
}
U32 get_radio_size(void)
{
return get_pt_table_all_size_general(PT_ISP);
}
S32 flash_write_af(U8 *buf, U32 buflen)
{
ARG arg = {0};
#ifdef USE_NAND_FLASH
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
return write_pt_table_data_general(&arg,PT_AF_FILE,0);
#else
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
strcpy(arg.pt_name,PT_AF);
return write_pt_table_data_general(&arg,NULL,0);
#endif
}
S32 flash_read_af(U8 *buf, U32 buflen)
{
ARG arg = {0};
#ifdef USE_NAND_FLASH
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
return read_flash_pt_data_general(&arg,PT_AF_FILE);
#else
arg.offset = 0;
arg.length = buflen;
arg.rw_buf = buf;
strcpy(arg.pt_name,PT_AF);
return read_flash_pt_data_general(&arg,NULL);
#endif
}
U32 get_af_size(void)
{
#ifdef USE_NAND_FLASH
return AF_DATA_MAX_SIZE;
#else
return get_pt_table_all_size_general(PT_AF);
#endif
}
#ifdef VIGI_USR_DEF_AUDIO_ALARM
#define MAX_USR_ALARM_NUM 3
S32 flash_write_usr_audio(U8 *buf, U32 buflen, U32 sub_index)
{
ARG arg = {0};
char file_name[128] = {0};
arg.rw_buf = buf;
arg.length = buflen;
snprintf(file_name,128,"%s_%d.audio",USR_AUDIO_FILE,sub_index);
return write_pt_table_data_general(&arg,file_name,0);
}
S32 flash_read_usr_audio(U8 *buf, U32 buflen, U32 sub_index)
{
ARG arg = {0};
char file_name[128] = {0};
arg.rw_buf = buf;
arg.length = buflen;
snprintf(file_name,128,"%s_%d.audio",USR_AUDIO_FILE,sub_index);
return read_flash_pt_data_general(&arg,file_name);
}
S32 flash_erase_usr_audio()
{
int ret = 0;
char file_name[128] = {0};
short usr_id = 0;
for (usr_id = 0;usr_id < MAX_USR_ALARM_NUM;usr_id++)
{
sprintf(file_name,"%s_%d.audio",USR_AUDIO_FILE,usr_id);
ret = erase_pt_table_data_general(NULL,file_name,0,0);
if (ret)
return ret;
}
return 0;
}
#endif
S32 flash_write_facinfo(U8 *buf, U32 buflen)
{
ARG arg = {0};
arg.offset = 0;
arg.rw_buf = buf;
arg.length = buflen;
strcpy(arg.pt_name,PT_FACTORY_INFO);
return write_pt_table_data_general(&arg,NULL,1);
}
S32 flash_read_facinfo(U8 *buf, U32 buflen)
{
ARG arg = {0};
arg.offset = 0;
arg.rw_buf = buf;
arg.length = buflen;
strcpy(arg.pt_name,PT_FACTORY_INFO);
return read_flash_pt_data_general(&arg,NULL);
}
U32 get_facinfo_size(void)
{
return get_pt_table_all_size_general(PT_FACTORY_INFO);
}
int del_flash_partition(char *name,int mtd_type)
{
ARG arg = {0};
int fd = 0,ret = -1;
pt_usr_table *pt_utb = NULL;
char cmd_buf[128] = {0};
fd = open(FLASH_DEV,O_WRONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
ret = -1;
goto exit;
}
switch (mtd_type)
{
case PARTITION_ITEM_TYPE_MTD:
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if ((pt_utb != raxNotFound && GET_PARTITION_ATTRIBUTE(DATA_DEL,pt_utb->pt_table->partition_attribute) == 1) || pt_utb == raxNotFound)
{
FLASHIO_ERROR("the pt %s is not in pt_table or is deleted",name);
ret = 0;
goto exit;
}
strcpy(arg.pt_name,name);
arg.mtd_info = pt_utb->mtd_info;
ret = ioctl(fd,SLP_DEL_PARTITION,&arg);
if (ret)
{
FLASHIO_ERROR("del %s error",arg.pt_name);
goto exit;
}
destroy_radix_node(name);
break;
case PARTITION_ITEM_TYPE_UBI:
pt_utb = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)name,strlen(name));
if (pt_utb == raxNotFound || (pt_utb->pt_table == NULL && pt_utb->vol_table == NULL))
{
FLASHIO_ERROR("the pt %s is not in pt_table or is deleted",name);
ret = 0;
goto exit;
}
if (pt_utb->vol_table)
{
sprintf(cmd_buf,"ubirmvol /dev/ubi%d -N %s",pt_utb->ubi_id,pt_utb->vol_table->vol_name);
ret = system(cmd_buf);
if (ret)
goto exit;
}
else if (pt_utb->pt_table)
{
sprintf(cmd_buf,"ubidetach -p /dev/mtd%d",pt_utb->mtd_id);
ret = system(cmd_buf);
if (ret)
goto exit;
arg.mtd_info = pt_utb->mtd_info;
strcpy(arg.pt_name,pt_utb->pt_table->partition_name);
ret = ioctl(fd,SLP_DEL_PARTITION,&arg);
if (ret)
{
FLASHIO_ERROR("not dele %s from ubi%d",name,pt_utb->ubi_id);
goto exit;
}
}
destroy_radix_node(name);
break;
}
exit:
if (fd > 0)
close(fd);
return ret;
}
int add_flash_partition(void *new_table,void *vol_table,int ubi_min_block)
{
ARG arg = {0};
int fd = 0,ret = -1;
partition_table_item *table = NULL,*table_tmp = NULL;
ubi_vol *vol = NULL,*vol_tmp = NULL;
pt_usr_table pt_utb = {0},*pt_utb_tmp = NULL;
char cmd_buf[128] = {0};
fd = open(FLASH_DEV,O_WRONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
ret = -1;
goto exit;
}
table = (partition_table_item *)new_table;
switch (GET_PARTITION_ATTRIBUTE(FLASH_TYPE,table->partition_attribute))
{
case PARTITION_ITEM_TYPE_MTD:
if (raxFind(rax_ctx,(unsigned char *)table->partition_name,strlen(table->partition_name)) != raxNotFound)
{
FLASHIO_ERROR("the pt %s is added",table->partition_name);
goto exit;
}
pt_utb_tmp = raxFind(rax_ctx,(unsigned char *)"pt_table",strlen("pt_table"));
if (pt_utb_tmp == raxNotFound)
goto exit;
strcpy(arg.pt_name,table->partition_name);
arg.offset = table->partition_offset;
arg.length = table->partition_length;
arg.mtd_info = pt_utb_tmp->mtd_info;
ret = ioctl(fd,SLP_ADD_PARTITION,&arg);
if (ret)
{
FLASHIO_ERROR("add %s error",arg.pt_name);
goto exit;
}
table_tmp = calloc(sizeof(partition_table_item),1);
if (table_tmp == NULL)
goto del_pt_exit;
memcpy(table_tmp,table,sizeof(partition_table_item));
pt_utb.mtd_info = arg.mtd_info;
pt_utb.pt_table = table_tmp;
pt_utb.mtd_id = arg.mtd_id;
pt_utb.free_flag = 1;
table_tmp = NULL;
ret = add_radix_node(&pt_utb,pt_utb.pt_table->partition_name);
if (ret)
goto del_pt_exit;
break;
case PARTITION_ITEM_TYPE_UBI:
if (raxFind(rax_ctx,(unsigned char *)table->partition_name,strlen(table->partition_name)) == raxNotFound)
{
pt_utb_tmp = raxFind(rax_ctx,(unsigned char *)"pt_table",strlen("pt_table"));
if (pt_utb_tmp == raxNotFound)
goto exit;
strcpy(arg.pt_name,table->partition_name);
arg.mtd_info = pt_utb_tmp->mtd_info;
arg.offset = table->partition_offset;
arg.length = table->partition_length;
arg.min_erase_block = ubi_min_block;
ret = ioctl(fd,SLP_ADD_PARTITION,&arg);
if (ret)
{
FLASHIO_ERROR("add %s error",arg.pt_name);
goto exit;
}
arg.offset = 0;
ret = ioctl(fd,SLP_IOC_FLASH_ERASE,&arg);
if (ret)
{
FLASHIO_ERROR("erase %s error",arg.pt_name);
goto del_pt_exit;
}
sprintf(cmd_buf,"ubiformat /dev/mtd%d -y",arg.mtd_id);
ret = system(cmd_buf);
if (ret)
goto del_pt_exit;
sprintf(cmd_buf,"ubiattach -p /dev/mtd%d",arg.mtd_id);
ret = system(cmd_buf);
if (ret)
goto del_pt_exit;
ret = ioctl(fd,SLP_IOC_FLASH_GET_INFO,&arg);
if (ret)
{
FLASHIO_ERROR("get %s error",arg.pt_name);
goto del_pt_exit;
}
pt_utb.ubi_id = arg.ubi_id;
if (pt_utb.ubi_id == -1)
{
FLASHIO_ERROR("the mtd ubi is invalid");
goto del_pt_exit;
}
table_tmp = calloc(sizeof(partition_table_item),1);
if (table_tmp == NULL)
goto del_pt_exit;
memcpy(table_tmp,table,sizeof(partition_table_item));
pt_utb.mtd_info = arg.mtd_info;
pt_utb.pt_table = table_tmp;
pt_utb.mtd_id = arg.mtd_id;
pt_utb.free_flag = 1;
ret = add_radix_node(&pt_utb,pt_utb.pt_table->partition_name);
if (ret)
goto del_pt_exit;
table_tmp = NULL;
pt_utb_tmp = &pt_utb;
}
else
pt_utb_tmp = (pt_usr_table *)raxFind(rax_ctx,(unsigned char *)table->partition_name,strlen(table->partition_name));
vol = (ubi_vol *)vol_table;
if (raxFind(rax_ctx,(unsigned char *)vol->vol_name,strlen(vol->vol_name)) == raxNotFound)
{
sprintf(cmd_buf,"ubimkvol -s %d /dev/ubi%d -N %s",vol->vol_size,pt_utb_tmp->ubi_id,vol->vol_name);
ret = system(cmd_buf);
if (ret)
goto exit;
strcpy(arg.pt_name,vol->vol_name);
ret = ioctl(fd,SLP_IOC_FLASH_GET_INFO,&arg);
if (ret)
{
FLASHIO_ERROR("get %s error",arg.pt_name);
goto del_vol_exit;
}
pt_utb.ubi_id = arg.ubi_id;
if (pt_utb.ubi_id == -1)
{
FLASHIO_ERROR("the mtd ubi is invalid");
goto del_vol_exit;
}
vol_tmp = calloc(sizeof(ubi_vol),1);
if (vol_tmp == NULL)
goto del_vol_exit;
memcpy(vol_tmp,vol,sizeof(ubi_vol));
pt_utb.mtd_info = arg.mtd_info;
pt_utb.vol_table = vol_tmp;
pt_utb.mtd_id = arg.mtd_id;
pt_utb.free_flag = 1;
pt_utb.pt_table = NULL;
ret = add_radix_node(&pt_utb,pt_utb.vol_table->vol_name);
if (ret)
goto del_vol_exit;
vol_tmp = NULL;
}
break;
}
return 0;
del_pt_exit:
ioctl(fd,SLP_DEL_PARTITION,&arg);
goto exit;
del_vol_exit:
sprintf(cmd_buf,"ubirmvol /dev/ubi%d -N %s",pt_utb_tmp->ubi_id,vol->vol_name);
system(cmd_buf);
exit:
if (fd > 0)
close(fd);
if (table_tmp)
free(table_tmp);
if (vol_tmp)
free(vol_tmp);
return -1;
}
int flash_map_memory(char *pt_name)
{
ARG arg = {0};
int fd = 0,ret = -1;
pt_usr_table *pt_utb = NULL;
fd = open(FLASH_DEV,O_WRONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
goto exit;
}
pt_utb = raxFind(rax_ctx,(unsigned char *)pt_name,strlen(pt_name));
if (pt_utb == raxNotFound)
goto exit;
arg.mtd_info = pt_utb->mtd_info;
if (pt_utb->pt_table != NULL)
arg.length = pt_utb->pt_table->valid_size;
else if (pt_utb->vol_table != NULL)
arg.length = pt_utb->vol_table->valid_size;
else
{
FLASHIO_ERROR("unknown flash type,map forbid");
ret = -1;
goto exit;
}
arg.offset = 0;
ret = ioctl(fd, SLP_MAP_FLASH, &arg);
if (ret)
{
FLASHIO_ERROR("%s call ioctl failed", __func__);
close(fd);
return ERROR;
}
exit:
if (fd > 0)
close(fd);
return ret;
}
void switch_partition_table_to_network(TP_HEAD_INFO *tpheader)
{
partition_table_item *table = NULL;
ubi_vol *vol = NULL;
short pt_id = 0,vol_id = 0;
for (pt_id = 0;pt_id < tpheader->partition_num;pt_id++)
{
table = &(tpheader->table[pt_id]);
table->partition_attribute = htonl(table->partition_attribute);
table->partition_offset = htonl(table->partition_offset);
table->partition_length = htonl(table->partition_length);
table->partition_valid_size = htonl(table->partition_valid_size);
table->valid_size = htonl(table->valid_size);
table->version = htons(table->version);
table->fw_offset = htonl(table->fw_offset);
for (vol_id = 0;vol_id < UBI_MAX_NUM;vol_id++)
{
vol = &(table->vol_table[vol_id]);
if (strlen(vol->vol_name) == 0)
continue;
vol->fw_offset = htonl(vol->fw_offset);
vol->vol_size = htonl(vol->vol_size);
vol->valid_size = htonl(vol->valid_size);
vol->partition_attribute = htonl(vol->partition_attribute);
vol->vol_valid_size = htonl(vol->vol_valid_size);
vol->ubi_version = htons(vol->ubi_version);
}
}
tpheader->partition_num = htons(tpheader->partition_num);
}
void switch_partition_table_to_local(TP_HEAD_INFO *tpheader)
{
partition_table_item *table = NULL;
ubi_vol *vol = NULL;
short pt_id = 0,vol_id = 0;
tpheader->partition_num = ntohs(tpheader->partition_num);
for (pt_id = 0;pt_id < tpheader->partition_num;pt_id++)
{
table = &(tpheader->table[pt_id]);
table->partition_attribute = ntohl(table->partition_attribute);
table->partition_offset = ntohl(table->partition_offset);
table->partition_length = ntohl(table->partition_length);
table->partition_valid_size = ntohl(table->partition_valid_size);
table->valid_size = ntohl(table->valid_size);
table->version = ntohs(table->version);
table->fw_offset = ntohl(table->fw_offset);
for (vol_id = 0;vol_id < UBI_MAX_NUM;vol_id++)
{
vol = &(table->vol_table[vol_id]);
if (strlen(vol->vol_name) == 0)
continue;
vol->fw_offset = ntohl(vol->fw_offset);
vol->vol_size = ntohl(vol->vol_size);
vol->valid_size = ntohl(vol->valid_size);
vol->partition_attribute = ntohl(vol->partition_attribute);
vol->vol_valid_size = ntohl(vol->vol_valid_size);
vol->ubi_version = ntohs(vol->ubi_version);
}
}
}
int mark_bad_block(char *pt_name,int bad_block)
{
ARG arg = {0};
int fd = 0,ret = -1;
pt_usr_table *pt_utb = NULL;
fd = open(FLASH_DEV,O_WRONLY);
if (fd <= 0)
{
FLASHIO_ERROR("open flash dev error");
goto exit;
}
pt_utb = raxFind(rax_ctx,(unsigned char *)pt_name,strlen(pt_name));
if (pt_utb == raxNotFound)
goto exit;
arg.mtd_info = pt_utb->mtd_info;
if (pt_utb->pt_table != NULL)
arg.offset = bad_block;
else
{
FLASHIO_ERROR("not flash type,mark bad forbid");
ret = -1;
goto exit;
}
ret = ioctl(fd, SLP_MAP_MARK_BAD, &arg);
if (ret)
{
FLASHIO_ERROR("%s call ioctl failed", __func__);
close(fd);
return ERROR;
}
exit:
if (fd > 0)
close(fd);
return ret;
}
#ifdef FUNCTION_MODE
#ifdef USE_NAND_FLASH
S32 flash_write_tp_mode(U8 *buf, U32 buflen)
{
//可直接读写的分区都用ubifs
struct stat st;
if (stat(UC_PART_PATH,&st) != 0)
{
FLASHIO_ERROR("%s not exit", UC_PART_PATH);
return ERROR;
}
char *name = TP_MODE_FILE_DIR "/" TP_MODE_FILE_PATH;
FILE *cfg = fopen(name,"wb+");
if (cfg == NULL)
{
FLASHIO_ERROR("open %s failed",name);
return ERROR;
}
int retLen = fwrite(buf,1,buflen,cfg);
if (retLen != buflen)
{
FLASHIO_ERROR("file not write ok");
return ERROR;
}
int fd = fileno(cfg);
drop_file_cache(fd,TRUE); //将缓存写入文件
fclose(cfg);
return OK;
}
S32 flash_read_tp_mode(U8 *buf, U32 buflen)
{
//可直接读写的分区都用ubifs
struct stat st;
if (stat(UC_PART_PATH,&st) != 0)
{
FLASHIO_ERROR("%s not exit", UC_PART_PATH);
return ERROR;
}
char *name = TP_MODE_FILE_DIR "/" TP_MODE_FILE_PATH;
FILE *cfg = fopen(name,"rb");
if (cfg == NULL)
{
FLASHIO_ERROR("open %s failed",name);
return ERROR;
}
int retLen = fread(buf,1,buflen,cfg);
if (retLen <= 0)
{
FLASHIO_ERROR("file not read ok");
return ERROR;
}
fclose(cfg);
return OK;
}
#else
/*nor flash 读写tp_mode */
S32 flash_write_tp_mode(U8 *buf, U32 buflen)
{
ARG arg;
S32 ret = -1;
S32 fd = -1;
arg.addr = (U32)TP_MODE_NOR_FLASH_OFFSET;
arg.buf = buf;
arg.len = buflen;
fd = open(FLASH_DEV, O_RDONLY);
if (-1 == fd)
{
FLASHIO_ERROR("open device failed");
return ERROR;
}
ret = ioctl(fd, SLP_IOC_FLASH_WRITE, &arg);
if (ret)
{
FLASHIO_ERROR("ioctl failed, errcode %d", ret);
close(fd);
return ERROR;
}
printf("flash_write_tp_mode\n");
close(fd);
return OK;
}
S32 flash_read_tp_mode(U8 *buf, U32 buflen)
{
ARG arg;
S32 ret = -1;
S32 fd = -1;
arg.addr = (U32)TP_MODE_NOR_FLASH_OFFSET;
arg.buf = buf;
arg.len = buflen;
fd = open(FLASH_DEV, O_RDONLY);
if (-1 == fd)
{
FLASHIO_ERROR("open device failed");
return ERROR;
}
ret = ioctl(fd, SLP_IOC_FLASH_READ, &arg);
if (ret)
{
FLASHIO_ERROR("ioctl failed, errcode %d", ret);
close(fd);
return ERROR;
}
printf("flash_read_tp_mode\n");
close(fd);
return OK;
}
#endif
#endif
FLASH_USR_SPACE_MODULE_INIT(init_flash_io);