blob: 9e495895c9511e4824271af6f49a01d41333418f [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
#include "otad.h"
#include "mbtk_type.h"
#include "mbtk_device.h"
typedef struct {
char name[32];
char dev[16];
uint32 partition_start;
uint32 partition_size;
uint32 erase_size;
} partition_info_t;
/*
* revision_out start from 0x1000.
*/
#define REVISION_OUT_ADDR 0x1000
char revision_out[48] = {0};
static bool revision_out_found = FALSE;
static int partition_get(char *partition_name, partition_info_t *info)
{
FILE *fp = fopen("/proc/mtd", "r");
if(fp == NULL) {
OTA_ERR("fopen(/proc/mtd) fail:%d", errno);
return -1;
}
char buff[64];
char size_str[16];
char erase_size_str[16];
char name[32];
memset(buff, 0x0, sizeof(buff));
while(fgets(buff, sizeof(buff), fp)) {
if(strstr(buff, partition_name)) {
memset(size_str, 0x0, sizeof(size_str));
memset(erase_size_str, 0x0, sizeof(erase_size_str));
memset(name, 0x0, sizeof(name));
memcpy(info->dev, "/dev/", 5);
if(4 == sscanf(buff, "%s %s %s %s", info->dev + 5, size_str, erase_size_str, name)) {
if(name[0] == '\"' && name[strlen(name) - 1] == '\"') {
memcpy(info->name, name + 1, strlen(name) - 2); // No copy ""
} else {
OTA_ERR("partition(%s) name error.", buff);
return -1;
}
if(info->dev[strlen(info->dev) - 1] == ':') {
info->dev[strlen(info->dev) - 1] = '\0';
}
info->partition_size = (uint32)strtoul(size_str, NULL, 16);
info->erase_size = (uint32)strtoul(erase_size_str, NULL, 16);
//info->partition_start += info->partition_size;
break;
} else {
OTA_ERR("sscanf(%s) fail:%d", buff, errno);
return -1;
}
}
memset(buff, 0x0, sizeof(buff));
}
fclose(fp);
return 0;
}
void revision_out_find(char *data, int len, unsigned int processed_cnt)
{
if(!revision_out_found) {
if(processed_cnt + len > REVISION_OUT_ADDR) { // µ½´ï 0x1000
char *start = NULL;
if(strlen(revision_out) > 0) {
start = data;
} else {
start = data + REVISION_OUT_ADDR - processed_cnt;
}
if(data[len - 1] == '\0') { // Last char is '\0',get the complete version.
if(strlen(start) > 0) {
memcpy(revision_out + strlen(revision_out), start, strlen(start));
}
revision_out_found = TRUE;
OTA_DEBUG("Found complete version : %s", revision_out);
} else {
memcpy(revision_out + strlen(revision_out), start, data + len - start);
OTA_DEBUG("Found version : %s", revision_out);
}
}
}
}
int revision_out_update()
{
if(strlen(revision_out) == 0) {
OTA_ERR("revision_out not set.");
revision_out_found = FALSE;
return -1;
}
partition_info_t info;
memset(&info, 0x0, sizeof(partition_info_t));
if(partition_get("device_info", &info)) {
OTA_ERR("partition_get() fail.");
return -1;
}
OTA_DEBUG("device_info name : %s, dev : %s, addr : %08x, size : %08x, erase_size : %08x", info.name,
info.dev, info.partition_start, info.partition_size, info.erase_size);
if(info.erase_size <= 0 || info.partition_size <= 0) {
OTA_ERR("partition info error.");
return -1;
}
#if 0
int fd = open(dev, O_RDWR);
if (fd < 0) {
OTA_ERR("Fatal error: can't open device_info %s\n", dev);
return -1;
}
mbtk_device_info_header_t info_header;
memset(&info_header, 0x0, sizeof(mbtk_device_info_header_t));
int len = read(fd, &info_header, sizeof(mbtk_device_info_header_t));
if (len != sizeof(mbtk_device_info_header_t)) {
OTA_ERR("Fatal error: read %d bytes(expect %d)\n", len, sizeof(mbtk_device_info_header_t));
goto fail;
}
if(info_header.tag != MBTK_DEVICE_INFO_PARTITION_TAG) {
OTA_ERR("TAG error : %08x", info_header.tag);
goto fail;
}
if(info_header.version != MBTK_DEVICE_INFO_CURR_VERSION) {
OTA_ERR("Version error : %d", info_header.version);
goto fail;
}
if(info_header.item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr == 0) {
OTA_ERR("No found item : %d", MBTK_DEVICE_INFO_ITEM_BASIC);
goto fail;
}
lseek(fd, info_header.item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr, SEEK_SET);
mbtk_device_info_basic_t info_basic;
memset(&info_basic, 0, sizeof(mbtk_device_info_basic_t));
if (read(fd, &info_basic, sizeof(mbtk_device_info_basic_t)) != sizeof(mbtk_device_info_basic_t)) {
OTA_ERR("Read fail:%d", errno);
goto fail;
}
memset(info_basic.revision_out, 0, sizeof(info_basic.revision_out));
memcpy(info_basic.revision_out, revision_out, strlen(revision_out));
lseek(fd, info_header.item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr, SEEK_SET);
if (write(fd, &info_basic, sizeof(mbtk_device_info_basic_t)) != sizeof(mbtk_device_info_basic_t)) {
OTA_ERR("Write fail:%d", errno);
goto fail;
}
#else
int fd = open(info.dev, O_RDWR);
if (fd < 0) {
OTA_ERR("Fatal error: can't open device_info %s\n", info.dev);
return -1;
}
char *mtd_buff = (char*)malloc(info.erase_size);
if(mtd_buff == NULL) {
OTA_ERR("malloc() failed\n");
return -1;
}
memset(mtd_buff, 0, info.erase_size);
int len = read(fd, mtd_buff, info.erase_size);
if (len != info.erase_size) {
OTA_ERR("Fatal error: read %d[%d] bytes(expect %d)\n", len, errno, info.erase_size);
goto fail;
}
struct erase_info_user mtdEraseInfo;
if (lseek(fd, 0, SEEK_SET) < 0)
{
OTA_ERR("seek failed\n");
return -1;
}
mtdEraseInfo.length = info.partition_size;
mtdEraseInfo.start = 0;
ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
ioctl(fd, MEMERASE, &mtdEraseInfo);
mbtk_device_info_header_t *info_header = (mbtk_device_info_header_t*)mtd_buff;
mbtk_device_info_basic_t *info_basic = (mbtk_device_info_basic_t*)(mtd_buff + info_header->item_header[MBTK_DEVICE_INFO_ITEM_BASIC].addr);
OTA_DEBUG("Old version : %s", info_basic->revision_out);
memset(info_basic->revision_out, 0, sizeof(info_basic->revision_out));
memcpy(info_basic->revision_out, revision_out, strlen(revision_out));
lseek(fd, 0, SEEK_SET);
if (write(fd, mtd_buff, info.erase_size) != info.erase_size) {
OTA_ERR("Write fail:%d", errno);
goto fail;
}
if(mtd_buff) {
free(mtd_buff);
}
#endif
close(fd);
OTA_DEBUG("Set revision_out : %s", revision_out);
memset(revision_out, 0x0, sizeof(revision_out));
revision_out_found = FALSE;
return 0;
fail:
close(fd);
return -1;
}