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