#include #include #include #include #include #include #include #include "libota.h" #include "fwinfo.h" static void print_hex(char *data, int len) { int i = 0; printf("\r\n"); for(i=0;i> 1) ^ 0xA001; } // 0xA001 = reverse 0x8005 else { crc = (crc >> 1); } } } return crc; } /****************************************************************************** * Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Poly: 0x4C11DB7 * Init: 0xFFFFFFF * Refin: True * Refout: True * Xorout: 0xFFFFFFF * Alias: CRC_32/ADCCP * Use: WinRAR,ect. *****************************************************************************/ uint32 fwinfo_crc32(const uint8 *data, uint32 length) { uint8 i; uint32 crc = 0xffffffff; // Initial value while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) { crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7 } else { crc = (crc >> 1); } } } return ~crc; } int32 fwinfo_check_fwinfo_hdr(const uint8 *data) { struct fwinfo_hdr *fw_hdr = NULL; if (data == NULL) { fwinfo_err("%s:Input para error!\n", __FUNCTION__); return -EINVAL; } //print_hex(data, 64); fw_hdr = (struct fwinfo_hdr *)data; if (fw_hdr->boot.boot_flag != FWINFO_BOOT_HDR) { fwinfo_err("%s:Can not find boot header!\n", __FUNCTION__); return -EINVAL;; } if (fw_hdr->fw_infor.func_code != FWINFO_CODE_HDR) { fwinfo_err("%s:Can not find fw infor header %x!\n", __FUNCTION__, fw_hdr->fw_infor.func_code); return -EINVAL;; } if (fw_hdr->spi_infor.func_code != FWINFO_SPI_HDR) { fwinfo_err("%s:Can not find spi info header!\n", __FUNCTION__); return -EINVAL; } return 0; } uint16 fwinfo_get_fw_aes_en(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:aes_en:%d\n", __FUNCTION__, fw_hdr->boot.mode.aes_en); *err_code = 0; return fw_hdr->boot.mode.aes_en; } uint16 fwinfo_get_fw_crc_en(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:crc_en:%d\n", __FUNCTION__, fw_hdr->boot.mode.crc_en); *err_code = 0; return fw_hdr->boot.mode.crc_en; } uint32 fwinfo_get_fw_dl_addr(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:download addr:%x\n", __FUNCTION__, fw_hdr->boot.boot_to_sram_addr); *err_code = 0; return fw_hdr->boot.boot_to_sram_addr; } uint32 fwinfo_get_fw_run_addr(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:run addr:%x\n", __FUNCTION__, fw_hdr->boot.run_sram_addr); *err_code = 0; return fw_hdr->boot.run_sram_addr; } uint32 fwinfo_get_fw_code_offset(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:code offset:%d\n", __FUNCTION__, fw_hdr->boot.boot_code_offset_addr); *err_code = 0; return fw_hdr->boot.boot_code_offset_addr; } uint32 fwinfo_get_fw_local_crc32(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:local crc:%x\n", __FUNCTION__, fw_hdr->fw_infor.code_crc32); *err_code = 0; return fw_hdr->fw_infor.code_crc32; } uint32 fwinfo_get_fw_sdk_version(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Current file sdk info:%d.%d.%d.%d\r\n", __FUNCTION__, (fw_hdr->fw_infor.sdk_version >> 24) & 0xff, (fw_hdr->fw_infor.sdk_version >> 16) & 0xff, (fw_hdr->fw_infor.sdk_version >> 8) & 0xff, (fw_hdr->fw_infor.sdk_version & 0xff)); *err_code = 0; return fw_hdr->fw_infor.sdk_version; } uint32 fwinfo_get_fw_svn_version(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Current file svn info:%d\n", __FUNCTION__, fw_hdr->fw_infor.svn_version); *err_code = 0; return fw_hdr->fw_infor.svn_version; } uint16 fwinfo_get_fw_chipid(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:fw chipid:%x\n", __FUNCTION__, fw_hdr->fw_infor.chip_id); *err_code = 0; return fw_hdr->fw_infor.chip_id; } uint8 fwinfo_get_fw_cpuid(const uint8 *data, int32 *err_code) { struct fwinfo_hdr *fw_hdr = NULL; int32 ret = 0; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } fw_hdr = (struct fwinfo_hdr *)data; fwinfo_dbg("%s:Check Para:cpu_id:%d\n", __FUNCTION__, fw_hdr->fw_infor.cpu_id); *err_code = 0; return fw_hdr->fw_infor.cpu_id; } uint32 fwinfo_get_fw_length(const uint8 *data, int32 *err_code) { int32 ret = 0; struct fwinfo_hdr *fw_hdr = (struct fwinfo_hdr *)data; ret = fwinfo_check_fwinfo_hdr(data); if (ret) { fwinfo_err("%s:fwinfo_check_fwinfo_hdr error!\n", __FUNCTION__); *err_code = ret; return -1; } *err_code = 0; return fw_hdr->boot.boot_from_flash_len + fw_hdr->boot.boot_code_offset_addr; } int32 fwinfo_get_fw_code_checksum(const uint8 *data, int32 len) { uint32 local_chksum = 0; uint32 cur_crc = 0; int32 err_code = 0; uint32 code_offset = 0; const uint8 *code_data = NULL; int32 code_len = 0; local_chksum = fwinfo_get_fw_local_crc32(data, &err_code); if (err_code != 0) { fwinfo_err("%s:fwinfo_get_fw_local_crc32 error!\n", __FUNCTION__); return err_code; } code_offset = fwinfo_get_fw_code_offset(data, &err_code); if (err_code != 0) { fwinfo_err("%s:fwinfo_get_fw_code_offset error!\n", __FUNCTION__); return err_code; } code_data = data + code_offset; code_len = len - code_offset; if (code_len < 0) { fwinfo_err("%s:Input para error!\n", __FUNCTION__); return -EINVAL; } cur_crc = fwinfo_crc32(code_data, code_len); if (cur_crc != local_chksum && ~cur_crc != local_chksum) { fwinfo_err("%s:Check crc32 with hdr crc error,local crc:%x,cur_crc:%x\r\n", __FUNCTION__, local_chksum, cur_crc); return -EFAULT; } fwinfo_dbg("%s:Checksum Success!\n", __FUNCTION__); return 0; }