当前位置:网站首页>GD32 RT-Thread OTA/Bootloader驱动函数
GD32 RT-Thread OTA/Bootloader驱动函数
2022-06-30 09:37:00 【Sky_Lannister】
GD32 OTA/Bootloader驱动函数
驱动函数需要修改一个文件rt_fota.c,添加内部flash操作相关文件,删除外部flash操作相关文件,移植过程注意事项及其它外设移植细节参见 移植完整版RT-Thread到GD32F4XX(详细) 中关于bootloader及flash移植相关内容,移植完成后使用及验证方法同stm32
原开源项目位于https://gitee.com/spunky_973/rt-fota,只适配了stm32f4系列,未实现hash校验;本博客所做改动仅为适配GD32F4XX系列,及添加了hash校验(已提交PR),同时修改片外升级为片内升级,进一步缩小bootloader大小,开源地址为https://gitee.com/yangfei_addoil/rt-fota-gd32
rt_fota.c
//添加hash校验 通过RT_FOTA_USE_HASH进行开启关闭
//hash fnv1a
#define FNV_SEED 0x811c9dc5
#define DATA_LEN 355232
int rt_fota_check_hash(const char *part_name);
static uint32_t fnv1a_r(uint8_t oneByte, uint32_t hash)
{
return ((oneByte ^ hash) * 0x1000193);
}
static uint32_t calc(uint8_t * data, uint32_t hash, long len)
{
for (int i = 0; i < len; i++)
{
hash = fnv1a_r(data[i], hash);
}
return hash;
}
#ifdef RT_FOTA_USE_HASH
/** * @brief check hash value * @note * @param part_name: flash name * * @retval rt_fota_err_t * @author yangFei * @date 20220620 * @note similar to rt_fota_upgrade,add before rt_fota_upgrade of rt_fota_thread_entry */
int rt_fota_check_hash(const char *part_name)
{
uint32_t hash_value = 0;
int fota_err = RT_FOTA_NO_ERR;
const struct fal_partition *part;
rt_fota_part_head_t part_head = RT_NULL;
tiny_aes_context *aes_ctx = RT_NULL;
rt_uint8_t *aes_iv = RT_NULL;
rt_uint8_t *crypt_buf = RT_NULL;
int fw_raw_pos = 0;
int fw_raw_len = 0;
rt_uint32_t total_copy_size = 0;
rt_uint8_t block_hdr_buf[RT_FOTA_BLOCK_HEADER_SIZE];
rt_uint32_t block_hdr_pos = RT_FOTA_ALGO_BUFF_SIZE;
rt_uint32_t block_size = 0;
rt_uint32_t dcprs_size = 0;
qlz_state_decompress *dcprs_state = RT_NULL;
rt_uint8_t *cmprs_buff = RT_NULL;
rt_uint8_t *dcprs_buff = RT_NULL;
rt_uint32_t padding_size = 0;
if (part_name == RT_NULL)
{
LOG_D("Invaild paramenter input!");
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
part = fal_partition_find(part_name);
if (part == RT_NULL)
{
LOG_D("check hash partition[%s] not found.", part_name);
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
/* Application partition erase */
fota_err = rt_fota_erase_app_part();
if (fota_err != RT_FOTA_NO_ERR)
{
goto __exit_check_hash;
}
/* rt_fota_erase_app_part() has check fota_part_head vaild already */
part_head = &fota_part_head;
crypt_buf = rt_malloc(RT_FOTA_ALGO_BUFF_SIZE);
if (crypt_buf == RT_NULL)
{
LOG_D("Not enough memory for firmware buffer.");
fota_err = RT_FOTA_NO_MEM_ERR;
goto __exit_check_hash;
}
/* AES256 algorithm enable */
if ((part_head->fota_algo & RT_FOTA_CRYPT_STAT_MASK) == RT_FOTA_CRYPT_ALGO_AES256)
{
aes_ctx = rt_malloc(sizeof(tiny_aes_context));
aes_iv = rt_malloc(rt_strlen(RT_FOTA_ALGO_AES_IV) + 1);
if (aes_ctx == RT_NULL || aes_iv == RT_NULL)
{
LOG_D("Not enough memory for firmware hash verify.");
fota_err = RT_FOTA_NO_MEM_ERR;
goto __exit_check_hash;
}
rt_memset(aes_iv, 0x0, rt_strlen(RT_FOTA_ALGO_AES_IV) + 1);
rt_memcpy(aes_iv, RT_FOTA_ALGO_AES_IV, rt_strlen(RT_FOTA_ALGO_AES_IV));
tiny_aes_setkey_dec(aes_ctx, (rt_uint8_t *)RT_FOTA_ALGO_AES_KEY, 256);
}
else if ((part_head->fota_algo & RT_FOTA_CRYPT_STAT_MASK) == RT_FOTA_CRYPT_ALGO_XOR)
{
LOG_I("Not surpport XOR.");
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
/* If enable fastlz compress function */
if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_FASTLZ)
{
cmprs_buff = rt_malloc(RT_FOTA_CMPRS_BUFFER_SIZE + RT_FOTA_FASTLZ_BUFFER_PADDING);
dcprs_buff = rt_malloc(RT_FOTA_CMPRS_BUFFER_SIZE);
if (cmprs_buff == RT_NULL || dcprs_buff == RT_NULL)
{
LOG_D("Not enough memory for firmware hash verify.");
fota_err = RT_FOTA_NO_MEM_ERR;
goto __exit_check_hash;
}
padding_size = RT_FOTA_FASTLZ_BUFFER_PADDING;
}
else if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_QUICKLZ)
{
cmprs_buff = rt_malloc(RT_FOTA_CMPRS_BUFFER_SIZE + RT_FOTA_QUICKLZ_BUFFER_PADDING);
dcprs_buff = rt_malloc(RT_FOTA_CMPRS_BUFFER_SIZE);
dcprs_state = rt_malloc(sizeof(qlz_state_decompress));
if (cmprs_buff == RT_NULL || dcprs_buff == RT_NULL || dcprs_state == RT_NULL)
{
LOG_D("Not enough memory for firmware hash verify.");
fota_err = RT_FOTA_NO_MEM_ERR;
goto __exit_check_hash;
}
padding_size = RT_FOTA_QUICKLZ_BUFFER_PADDING;
rt_memset(dcprs_state, 0x0, sizeof(qlz_state_decompress));
}
else if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_GZIP)
{
LOG_I("Not surpport GZIP.");
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
while (fw_raw_pos < part_head->com_size)
{
if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) != RT_FOTA_CRYPT_ALGO_NONE)
{
if (block_hdr_pos >= RT_FOTA_ALGO_BUFF_SIZE)
{
fw_raw_len = rt_fota_read_part(part, fw_raw_pos, aes_ctx, aes_iv, crypt_buf, RT_FOTA_ALGO_BUFF_SIZE);
if (fw_raw_len < 0)
{
LOG_D("AES256 algorithm failed.");
fota_err = RT_FOTA_PART_READ_ERR;
goto __exit_check_hash;
}
fw_raw_pos += fw_raw_len;
rt_memcpy(block_hdr_buf, crypt_buf, RT_FOTA_BLOCK_HEADER_SIZE);
block_size = block_hdr_buf[0] * (1 << 24) + block_hdr_buf[1] * (1 << 16) + block_hdr_buf[2] * (1 << 8) + block_hdr_buf[3];
rt_memset(cmprs_buff, 0x0, RT_FOTA_CMPRS_BUFFER_SIZE + padding_size);
rt_memcpy(cmprs_buff, &crypt_buf[RT_FOTA_BLOCK_HEADER_SIZE], block_size);
block_hdr_pos = RT_FOTA_BLOCK_HEADER_SIZE + block_size;
}
else
{
rt_uint8_t hdr_tmp_pos = 0;
while (block_hdr_pos < RT_FOTA_ALGO_BUFF_SIZE)
{
if (hdr_tmp_pos < RT_FOTA_BLOCK_HEADER_SIZE)
{
block_hdr_buf[hdr_tmp_pos++] = crypt_buf[block_hdr_pos++];
}
else
{
block_size = block_hdr_buf[0] * (1 << 24) + block_hdr_buf[1] * (1 << 16) + block_hdr_buf[2] * (1 << 8) + block_hdr_buf[3];
rt_memset(cmprs_buff, 0x0, RT_FOTA_CMPRS_BUFFER_SIZE + padding_size);
if (block_size > (RT_FOTA_ALGO_BUFF_SIZE - block_hdr_pos))
{
rt_memcpy(cmprs_buff, &crypt_buf[block_hdr_pos], (RT_FOTA_ALGO_BUFF_SIZE - block_hdr_pos));
fw_raw_len = rt_fota_read_part(part, fw_raw_pos, aes_ctx, aes_iv, crypt_buf, RT_FOTA_ALGO_BUFF_SIZE);
if (fw_raw_len < 0)
{
LOG_D("AES256 algorithm failed.");
fota_err = RT_FOTA_PART_READ_ERR;
goto __exit_check_hash;
}
fw_raw_pos += fw_raw_len;
rt_memcpy(&cmprs_buff[RT_FOTA_ALGO_BUFF_SIZE - block_hdr_pos], &crypt_buf[0], (block_size + block_hdr_pos) - RT_FOTA_ALGO_BUFF_SIZE);
block_hdr_pos = (block_size + block_hdr_pos) - RT_FOTA_ALGO_BUFF_SIZE;
}
else
{
rt_memcpy(cmprs_buff, &crypt_buf[block_hdr_pos], block_size);
block_hdr_pos = block_hdr_pos + block_size;
}
break;
}
}
if (hdr_tmp_pos < RT_FOTA_BLOCK_HEADER_SIZE)
{
fw_raw_len = rt_fota_read_part(part, fw_raw_pos, aes_ctx, aes_iv, crypt_buf, RT_FOTA_ALGO_BUFF_SIZE);
if (fw_raw_len < 0)
{
LOG_D("AES256 algorithm failed.");
fota_err = RT_FOTA_PART_READ_ERR;
goto __exit_check_hash;
}
fw_raw_pos += fw_raw_len;
block_hdr_pos = 0;
while (hdr_tmp_pos < RT_FOTA_BLOCK_HEADER_SIZE)
{
block_hdr_buf[hdr_tmp_pos++] = crypt_buf[block_hdr_pos++];
}
block_size = block_hdr_buf[0] * (1 << 24) + block_hdr_buf[1] * (1 << 16) + block_hdr_buf[2] * (1 << 8) + block_hdr_buf[3];
rt_memset(cmprs_buff, 0x0, RT_FOTA_CMPRS_BUFFER_SIZE + padding_size);
rt_memcpy(cmprs_buff, &crypt_buf[block_hdr_pos], block_size);
block_hdr_pos = (block_hdr_pos + block_size) % RT_FOTA_ALGO_BUFF_SIZE;
}
}
rt_memset(dcprs_buff, 0x0, RT_FOTA_CMPRS_BUFFER_SIZE);
if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_FASTLZ)
{
dcprs_size = fastlz_decompress((const void *)&cmprs_buff[0], block_size, &dcprs_buff[0], RT_FOTA_CMPRS_BUFFER_SIZE);
}
else if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_QUICKLZ)
{
dcprs_size = qlz_decompress((const char *)&cmprs_buff[0], &dcprs_buff[0], dcprs_state);
}
if (dcprs_size <= 0)
{
LOG_D("Decompress failed: %d.", dcprs_size);
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
if(total_copy_size == 0)
{
hash_value = calc(dcprs_buff, FNV_SEED, dcprs_size);
}
else
{
hash_value = calc(dcprs_buff, hash_value, dcprs_size);
}
total_copy_size += dcprs_size;
rt_kprintf("#");
}
/* no compress option */
else
{
fw_raw_len = rt_fota_read_part(part, fw_raw_pos, aes_ctx, aes_iv, crypt_buf, RT_FOTA_ALGO_BUFF_SIZE);
if (fw_raw_len < 0)
{
LOG_D("AES256 algorithm failed.");
fota_err = RT_FOTA_PART_READ_ERR;
goto __exit_check_hash;
}
fw_raw_pos += fw_raw_len;
if(total_copy_size == 0)
{
hash_value = calc(crypt_buf, FNV_SEED, fw_raw_len);
}
else if((total_copy_size / 1024) == (part_head->raw_size / 1024))
{
hash_value = calc(crypt_buf, hash_value, (part_head->raw_size - total_copy_size));
}
else
{
hash_value = calc(crypt_buf, hash_value, fw_raw_len);
}
total_copy_size += fw_raw_len;
rt_kprintf("#");
}
}
/* it has compress option */
if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) != RT_FOTA_CRYPT_ALGO_NONE)
{
while (total_copy_size < part_head->raw_size)
{
if ((block_hdr_pos < fw_raw_len) && ((fw_raw_len - block_hdr_pos) > RT_FOTA_BLOCK_HEADER_SIZE))
{
rt_memcpy(block_hdr_buf, &crypt_buf[block_hdr_pos], RT_FOTA_BLOCK_HEADER_SIZE);
block_size = block_hdr_buf[0] * (1 << 24) + block_hdr_buf[1] * (1 << 16) + block_hdr_buf[2] * (1 << 8) + block_hdr_buf[3];
if ((fw_raw_len - block_hdr_pos - RT_FOTA_BLOCK_HEADER_SIZE) >= block_size)
{
rt_memset(cmprs_buff, 0x0, RT_FOTA_CMPRS_BUFFER_SIZE + padding_size);
rt_memcpy(cmprs_buff, &crypt_buf[block_hdr_pos + RT_FOTA_BLOCK_HEADER_SIZE], block_size);
rt_memset(dcprs_buff, 0x0, RT_FOTA_CMPRS_BUFFER_SIZE);
block_hdr_pos += (block_size + RT_FOTA_BLOCK_HEADER_SIZE);
if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_FASTLZ)
{
dcprs_size = fastlz_decompress((const void *)&cmprs_buff[0], block_size, &dcprs_buff[0], RT_FOTA_CMPRS_BUFFER_SIZE);
}
else if ((part_head->fota_algo & RT_FOTA_CMPRS_STAT_MASK) == RT_FOTA_CMPRS_ALGO_QUICKLZ)
{
dcprs_size = qlz_decompress((const char *)&cmprs_buff[0], &dcprs_buff[0], dcprs_state);
}
if (dcprs_size <= 0)
{
LOG_D("Decompress failed: %d.", dcprs_size);
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
hash_value = calc(dcprs_buff, hash_value, dcprs_size);
total_copy_size += dcprs_size;
rt_kprintf("#");
}
else
{
break;
}
}
else
{
break;
}
}
}
rt_kprintf("\r\n");
#ifdef RT_FOTA_USE_HASH
/* add hash cal */
if(hash_value != part_head->hash_val)
{
rt_kprintf("hash value check failed.");
fota_err = RT_FOTA_GENERAL_ERR;
goto __exit_check_hash;
}
rt_kprintf("hash value check sucess.\r\n");
#endif
if (total_copy_size < part_head->raw_size)
{
LOG_D("Decompress check failed.");
fota_err = RT_FOTA_GENERAL_ERR;
}
__exit_check_hash:
if (aes_ctx)
rt_free(aes_ctx);
if (aes_iv)
rt_free(aes_iv);
if (crypt_buf)
rt_free(crypt_buf);
if (cmprs_buff)
rt_free(cmprs_buff);
if (dcprs_buff)
rt_free(dcprs_buff);
if (dcprs_state)
rt_free(dcprs_state);
if (fota_err == RT_FOTA_NO_ERR)
{
rt_kprintf("check success, total %d bytes.", total_copy_size);
}
return fota_err;
}
#endif
其它文件夹增删
见https://gitee.com/yangfei_addoil/rt-fota-gd32
边栏推荐
猜你喜欢
G 代码解释|最重要的 G 代码命令列表
Deploy lvs-dr cluster
Rider打开Unity脚本后没有提示
Shell script multi loop experiment
Nlopt -- Nonlinear Optimization -- principle introduction and application method
GNN hands on practice (II): reproduction graph attention network gat
《锦绣中华》中老年公益文旅游-走进佛山敬老院
著名画家史国良《丰收时节》数字藏品上线长城数艺
“昆明城市咖啡地图”活动再度开启
调试方法和技巧详解
随机推荐
NFS shared services
Brève description du collecteur d'ordures G1
unable to convert expression into double array
Harvester ch1 of CKB and HNS, connection tutorial analysis
MySQL advanced SQL statement of database (1)
Detailed explanation of commissioning methods and techniques
Shell script functions
Xinguan has no lover, and all the people benefit from loving deeds to warm the world -- donation to the public welfare action of Shangqiu children's welfare home
Oracle creates a stored procedure successfully, but the compilation fails
log4j
NLopt--非线性优化--原理介绍及使用方法
Guolin was crowned the third place of global popularity of perfect master in the third quarter of 2022
C語言實現掃雷遊戲,附詳解及完整代碼
Network based BGP
Compare the maximum computing power of the Cenozoic top ant s19xp and the existing s19pro in bitland
基于强化学习的股票量化交易Automated-Stock-Trading-Ensemble-Strategy
[JVM] brief introduction to CMS
Quick completion guide for manipulator (4): reducer of key components of manipulator
【JVM】G1垃圾回收器简述
华南产业集团发力数字经济,城链科技发布会成功召开