| /* |
| * mbtk_device_info.c |
| * |
| * MBTK device partition information utils. |
| * |
| */ |
| /****************************************************************************** |
| |
| EDIT HISTORY FOR FILE |
| |
| WHEN WHO WHAT,WHERE,WHY |
| -------- -------- ------------------------------------------------------- |
| 2024/2/27 LiuBin Initial version |
| |
| ******************************************************************************/ |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <sys/ioctl.h> |
| #include <mtd/mtd-user.h> |
| |
| #include "mbtk_type.h" |
| #include "mbtk_log.h" |
| #include "mbtk_str.h" |
| #include "mbtk_mtd.h" |
| |
| #include "mbtk_device.h" |
| |
| /* |
| * MBTK_DEVICE_INFO_ITEM_BASIC - mbtk_device_info_basic_t |
| * MBTK_DEVICE_INFO_ITEM_FOTA - mbtk_device_info_fota_t |
| * MBTK_DEVICE_INFO_ITEM_MODEM - mbtk_device_info_modem_t |
| * MBTK_DEVICE_INFO_ITEM_LOG - mbtk_device_info_log_t |
| */ |
| int mbtk_dev_info_read(mbtk_device_info_item_enum item_type, void *item_ptr, int item_size) |
| { |
| int fd, len, i; |
| mbtk_device_info_header_t info_header; |
| memset(&info_header, 0, sizeof(mbtk_device_info_header_t)); |
| |
| mbtk_partition_info_t *partition_info = mbtk_partition_get(); |
| if(partition_info == NULL) { |
| LOGE("mbtk_partition_get() fail."); |
| return -1; |
| } |
| |
| i = 0; |
| char dev[32] = {0}; |
| while(i < MBTK_PARTITION_NUM_MAX) { |
| if(partition_info[i].used && strcmp(partition_info[i].name, MBTK_DEVICE_INFO_PARTITION_NAME) == 0) { |
| snprintf(dev, 32, "/dev/%s", partition_info[i].dev); |
| LOGD("%s -> %s", partition_info[i].name, dev); |
| break; |
| } |
| i++; |
| } |
| if(strlen(dev) == 0) { |
| LOGE("DEV is null."); |
| return -1; |
| } |
| |
| fd = open(dev, O_RDONLY); |
| if (fd < 0) { |
| LOGE("Fatal error: can't open device_info %s\n", dev); |
| return -1; |
| } |
| |
| len = read(fd, &info_header, sizeof(mbtk_device_info_header_t)); |
| if (len != sizeof(mbtk_device_info_header_t)) { |
| LOGE("Fatal error: read %d bytes(expect %d)\n", len, sizeof(mbtk_device_info_header_t)); |
| close(fd); |
| goto fail; |
| } |
| |
| if(info_header.tag != MBTK_DEVICE_INFO_PARTITION_TAG) { |
| LOGE("TAG error : %08x", info_header.tag); |
| goto fail; |
| } |
| |
| LOGD("Dev info version : %d, Item count:%d", info_header.version, info_header.item_count); |
| |
| if(info_header.item_header[item_type].addr == 0) { |
| LOGE("No found item : %d", item_type); |
| goto fail; |
| } |
| |
| lseek(fd, info_header.item_header[item_type].addr, SEEK_SET); |
| |
| |
| switch(item_type) { |
| case MBTK_DEVICE_INFO_ITEM_BASIC: |
| { |
| if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_basic_t)) { |
| LOGE("ARG error:item-%d, item_size-%d", item_type, item_size); |
| goto fail; |
| } |
| |
| mbtk_device_info_basic_t *basic_ptr = (mbtk_device_info_basic_t*)item_ptr; |
| basic_ptr->version = (mbtk_device_info_version_enum)info_header.version; |
| if(basic_ptr->version == DEV_INFO_VERSION_V1) { |
| if (read(fd, &(basic_ptr->basic.v1), sizeof(mbtk_device_info_basic_v1_t)) != |
| sizeof(mbtk_device_info_basic_v1_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } else { |
| if (read(fd, &(basic_ptr->basic.v2), sizeof(mbtk_device_info_basic_v2_t)) != |
| sizeof(mbtk_device_info_basic_v2_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } |
| break; |
| } |
| case MBTK_DEVICE_INFO_ITEM_FOTA: |
| { |
| if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_fota_t)) { |
| LOGE("ARG error:item-%d, item_size-%d", item_type, item_size); |
| goto fail; |
| } |
| |
| mbtk_device_info_fota_t *fota_ptr = (mbtk_device_info_fota_t*)item_ptr; |
| fota_ptr->version = (mbtk_device_info_version_enum)info_header.version; |
| if(fota_ptr->version == DEV_INFO_VERSION_V1) { |
| if (read(fd, &(fota_ptr->fota.v1), sizeof(mbtk_device_info_fota_v1_t)) != |
| sizeof(mbtk_device_info_fota_v1_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } else { |
| if (read(fd, &(fota_ptr->fota.v2), sizeof(mbtk_device_info_fota_v2_t)) != |
| sizeof(mbtk_device_info_fota_v2_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } |
| break; |
| } |
| case MBTK_DEVICE_INFO_ITEM_MODEM: |
| { |
| if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_modem_t)) { |
| LOGE("ARG error:item-%d, item_size-%d", item_type, item_size); |
| goto fail; |
| } |
| |
| mbtk_device_info_modem_t *modem_ptr = (mbtk_device_info_modem_t*)item_ptr; |
| modem_ptr->version = (mbtk_device_info_version_enum)info_header.version; |
| if(modem_ptr->version == DEV_INFO_VERSION_V1) { |
| if (read(fd, &(modem_ptr->modem.v1), sizeof(mbtk_device_info_modem_v1_t)) != |
| sizeof(mbtk_device_info_modem_v1_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } else { |
| if (read(fd, &(modem_ptr->modem.v2), sizeof(mbtk_device_info_modem_v2_t)) != |
| sizeof(mbtk_device_info_modem_v2_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } |
| break; |
| } |
| case MBTK_DEVICE_INFO_ITEM_LOG: |
| { |
| if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_log_t)) { |
| LOGE("ARG error:item-%d, item_size-%d", item_type, item_size); |
| goto fail; |
| } |
| |
| mbtk_device_info_log_t *log_ptr = (mbtk_device_info_log_t*)item_ptr; |
| log_ptr->version = (mbtk_device_info_version_enum)info_header.version; |
| if(log_ptr->version == DEV_INFO_VERSION_V1) { |
| if (read(fd, &(log_ptr->log.v1), sizeof(mbtk_device_info_log_v1_t)) != |
| sizeof(mbtk_device_info_log_v1_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } else { |
| if (read(fd, &(log_ptr->log.v2), sizeof(mbtk_device_info_log_v2_t)) != |
| sizeof(mbtk_device_info_log_v2_t)) { |
| LOGE("Read fail:%d", errno); |
| goto fail; |
| } |
| } |
| break; |
| } |
| default: |
| { |
| LOGE("Item type[%d] error.", item_type); |
| goto fail; |
| } |
| } |
| |
| close(fd); |
| return 0; |
| |
| fail: |
| close(fd); |
| return -1; |
| } |
| |
| int mbtk_dev_info_write(mbtk_device_info_item_enum item_type, void *item_ptr, int item_size) |
| { |
| if(item_ptr == NULL) { |
| LOGE("ARG error."); |
| return -1; |
| } |
| |
| mbtk_partition_info_t info; |
| memset(&info, 0x0, sizeof(mbtk_partition_info_t)); |
| if(mbtk_partition_get_by_name(MBTK_DEVICE_INFO_PARTITION_NAME, &info)) { |
| LOGE("mbtk_partition_get_by_name() fail."); |
| return -1; |
| } |
| |
| LOGD("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) { |
| LOGE("partition info error."); |
| return -1; |
| } |
| |
| int fd = open(info.dev, O_RDWR); |
| if (fd < 0) { |
| LOGE("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) { |
| LOGE("malloc() failed\n"); |
| return -1; |
| } |
| memset(mtd_buff, 0xFF, info.erase_size); |
| int len = read(fd, mtd_buff, info.erase_size); |
| if (len != info.erase_size) { |
| LOGE("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) |
| { |
| LOGE("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; |
| switch(item_type) { |
| case MBTK_DEVICE_INFO_ITEM_BASIC: |
| { |
| if(item_size != sizeof(mbtk_device_info_basic_t)) { |
| LOGE("item_size != sizeof(mbtk_device_info_basic_t)\n\r"); |
| goto fail; |
| } |
| |
| mbtk_device_info_basic_t *basic_ptr = (mbtk_device_info_basic_t*)item_ptr; |
| if(info_header->version != basic_ptr->version) { |
| LOGE("basic version error."); |
| goto fail; |
| } |
| |
| if(basic_ptr->version == DEV_INFO_VERSION_V1) { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(basic_ptr->basic.v1), |
| sizeof(mbtk_device_info_basic_v1_t)); |
| } else { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(basic_ptr->basic.v2), |
| sizeof(mbtk_device_info_basic_v2_t)); |
| } |
| break; |
| } |
| case MBTK_DEVICE_INFO_ITEM_FOTA: |
| { |
| if(item_size != sizeof(mbtk_device_info_fota_t)) { |
| LOGE("item_size != sizeof(mbtk_device_info_fota_t)\n\r"); |
| goto fail; |
| } |
| |
| mbtk_device_info_fota_t *fota_ptr = (mbtk_device_info_fota_t*)item_ptr; |
| if(info_header->version != fota_ptr->version) { |
| LOGE("fota version error."); |
| goto fail; |
| } |
| |
| if(fota_ptr->version == DEV_INFO_VERSION_V1) { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(fota_ptr->fota.v1), |
| sizeof(mbtk_device_info_fota_v1_t)); |
| } else { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(fota_ptr->fota.v2), |
| sizeof(mbtk_device_info_fota_v2_t)); |
| } |
| break; |
| } |
| case MBTK_DEVICE_INFO_ITEM_MODEM: |
| { |
| if(item_size != sizeof(mbtk_device_info_modem_t)) { |
| LOGE("item_size != sizeof(mbtk_device_info_modem_t)\n\r"); |
| goto fail; |
| } |
| |
| mbtk_device_info_modem_t *modem_ptr = (mbtk_device_info_modem_t*)item_ptr; |
| if(info_header->version != modem_ptr->version) { |
| LOGE("modem version error."); |
| goto fail; |
| } |
| |
| if(modem_ptr->version == DEV_INFO_VERSION_V1) { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(modem_ptr->modem.v1), |
| sizeof(mbtk_device_info_modem_v1_t)); |
| } else { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(modem_ptr->modem.v2), |
| sizeof(mbtk_device_info_modem_v2_t)); |
| } |
| break; |
| } |
| case MBTK_DEVICE_INFO_ITEM_LOG: |
| { |
| if(item_size != sizeof(mbtk_device_info_log_t)) { |
| LOGE("item_size != sizeof(mbtk_device_info_log_t)\n\r"); |
| goto fail; |
| } |
| |
| mbtk_device_info_log_t *log_ptr = (mbtk_device_info_log_t*)item_ptr; |
| if(info_header->version != log_ptr->version) { |
| LOGE("log version error."); |
| goto fail; |
| } |
| |
| if(log_ptr->version == DEV_INFO_VERSION_V1) { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(log_ptr->log.v1), |
| sizeof(mbtk_device_info_log_v1_t)); |
| } else { |
| memcpy(mtd_buff + info_header->item_header[item_type].addr, &(log_ptr->log.v2), |
| sizeof(mbtk_device_info_log_v2_t)); |
| } |
| break; |
| } |
| default: |
| { |
| LOGE("Item type[%d] error.\n\r", item_type); |
| goto fail; |
| } |
| } |
| |
| lseek(fd, 0, SEEK_SET); |
| if (write(fd, mtd_buff, info.erase_size) != info.erase_size) { |
| LOGE("Write fail:%d", errno); |
| goto fail; |
| } |
| |
| if(mtd_buff) { |
| free(mtd_buff); |
| } |
| |
| close(fd); |
| return 0; |
| |
| fail: |
| close(fd); |
| return -1; |
| } |
| |
| int mbtk_dev_info_revision_get(char *revision_out, char *revision_in, char *project_cust, char *band_area, |
| char* build_time) |
| { |
| mbtk_device_info_basic_t info_basic; |
| memset(&info_basic, 0, sizeof(mbtk_device_info_basic_t)); |
| int result = mbtk_dev_info_read(MBTK_DEVICE_INFO_ITEM_BASIC, &info_basic, sizeof(mbtk_device_info_basic_t)); |
| if(result) { |
| LOGE("mbtk_dev_info_read(BASIC) fail."); |
| return -1; |
| } |
| |
| mbtk_device_info_modem_t info_modem; |
| memset(&info_modem, 0, sizeof(mbtk_device_info_modem_t)); |
| result = mbtk_dev_info_read(MBTK_DEVICE_INFO_ITEM_MODEM, &info_modem, sizeof(mbtk_device_info_modem_t)); |
| if(result) { |
| LOGE("mbtk_dev_info_read(MODEM) fail."); |
| return -1; |
| } |
| |
| mbtk_modem_band_area_enum modem_band_area = MBTK_MODEM_BAND_AREA_ALL; |
| if(info_basic.version == DEV_INFO_VERSION_V1) { |
| if(strlen((char*)info_basic.basic.v1.revision_out) > 0) { |
| memcpy(revision_out, info_basic.basic.v1.revision_out, strlen((char*)info_basic.basic.v1.revision_out)); |
| } |
| if(strlen((char*)info_basic.basic.v1.revision_in) > 0) { |
| memcpy(revision_in, info_basic.basic.v1.revision_in, strlen((char*)info_basic.basic.v1.revision_in)); |
| } |
| if(strlen((char*)info_basic.basic.v1.project_cust) > 0) { |
| memcpy(project_cust, info_basic.basic.v1.project_cust, strlen((char*)info_basic.basic.v1.project_cust)); |
| } |
| if(strlen((char*)info_basic.basic.v1.build_time) > 0) { |
| memcpy(build_time, info_basic.basic.v1.build_time, strlen((char*)info_basic.basic.v1.build_time)); |
| } |
| |
| modem_band_area = info_modem.modem.v1.band_area; |
| } else { |
| if(strlen((char*)info_basic.basic.v2.revision_out) > 0) { |
| memcpy(revision_out, info_basic.basic.v2.revision_out, strlen((char*)info_basic.basic.v2.revision_out)); |
| } |
| if(strlen((char*)info_basic.basic.v2.revision_in) > 0) { |
| memcpy(revision_in, info_basic.basic.v2.revision_in, strlen((char*)info_basic.basic.v2.revision_in)); |
| } |
| if(strlen((char*)info_basic.basic.v2.project_cust) > 0) { |
| memcpy(project_cust, info_basic.basic.v2.project_cust, strlen((char*)info_basic.basic.v2.project_cust)); |
| } |
| if(strlen((char*)info_basic.basic.v2.build_time) > 0) { |
| memcpy(build_time, info_basic.basic.v2.build_time, strlen((char*)info_basic.basic.v2.build_time)); |
| } |
| |
| modem_band_area = info_modem.modem.v2.band_area; |
| } |
| |
| switch(modem_band_area) { |
| case MBTK_MODEM_BAND_AREA_CN: |
| memcpy(band_area, "CN", 2); |
| break; |
| case MBTK_MODEM_BAND_AREA_EU: |
| memcpy(band_area, "EU", 2); |
| break; |
| case MBTK_MODEM_BAND_AREA_SA: |
| memcpy(band_area, "SA", 2); |
| break; |
| default: |
| memcpy(band_area, "DEF", 3); |
| break; |
| } |
| |
| return 0; |
| } |