1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #include "flash_fw_check.h"
19 #include "drivers.h"
20 #include "stack/ble/ble.h"
21 #include "tl_common.h"
22
23 static const unsigned long fw_crc32_half_tbl[16] = {
24 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
25 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
26
27 #define FW_READ_SIZE 256 // 16 // 256 require more stack space
28
29 u32 fw_crc_init = 0xFFFFFFFF;
30
31 /***********************************
32 * this function must be called after the function sys_init.
33 * sys_init will set the ota_program_offset value.
34 */
35 /**
36 * @brief This function is used to check the firmware is ok or not
37 * @param[in] crc_init_value - the initial value of CRC
38 * @return 0 - CRC is check success
39 * 1 - CRC is check fail
40 */
flash_fw_check(u32 crc_init_value)41 bool flash_fw_check(u32 crc_init_value)
42 {
43 if (!crc_init_value) {
44 fw_crc_init = 0xFFFFFFFF;
45 } else {
46 fw_crc_init = crc_init_value;
47 }
48
49 // find the real FW flash address
50 u32 fw_flashAddr;
51 if (!ota_program_offset) { // zero, firmware is stored at flash 0x20000.
52 fw_flashAddr = ota_program_bootAddr; // NOTE: this flash offset need to set according to OTA offset
53 } else { // note zero, firmware is stored at flash 0x00000.
54 fw_flashAddr = 0x00000;
55 }
56
57 u32 fw_size;
58 flash_read_page((fw_flashAddr + 0x18), 4, (u8 *)&fw_size); // 0x18 store bin size value
59
60 u16 fw_Block;
61 u16 fw_remainSizeByte;
62 fw_Block = fw_size / FW_READ_SIZE;
63 fw_remainSizeByte = fw_size % FW_READ_SIZE;
64
65 int i = 0;
66 u8 fw_tmpdata[FW_READ_SIZE]; //
67 u8 ota_dat[FW_READ_SIZE << 1];
68 for (i = 0; i < fw_Block; i++) { // Telink bin must align 16 bytes.
69 flash_read_page((fw_flashAddr + i * FW_READ_SIZE), FW_READ_SIZE, fw_tmpdata);
70
71 // FW_READ_SIZE byte OTA data32 half byteCRC
72 for (int i = 0; i < FW_READ_SIZE; i++) {
73 ota_dat[i * 2] = fw_tmpdata[i] & 0x0f;
74 ota_dat[i * 2 + 1] = fw_tmpdata[i] >> 4;
75 }
76 fw_crc_init = crc32_half_cal(fw_crc_init, ota_dat, (unsigned long *)fw_crc32_half_tbl, (FW_READ_SIZE << 1));
77 }
78
79 //////////////////////////////
80 if (fw_remainSizeByte != 4) {
81 flash_read_page((fw_flashAddr + fw_size - fw_remainSizeByte), (fw_remainSizeByte - 4), fw_tmpdata);
82 for (int i = 0; i < (fw_remainSizeByte - 4); i++) {
83 ota_dat[i * 2] = fw_tmpdata[i] & 0x0f;
84 ota_dat[i * 2 + 1] = fw_tmpdata[i] >> 4;
85 }
86 fw_crc_init =
87 crc32_half_cal(fw_crc_init, ota_dat, (unsigned long *)fw_crc32_half_tbl, ((fw_remainSizeByte - 4) << 1));
88 }
89
90 // read crc value and compare
91 u32 fw_check_value;
92 flash_read_page((fw_flashAddr + fw_size - 4), 4, (u8 *)&fw_check_value);
93
94 if (fw_check_value != fw_crc_init) {
95 return 1; // CRC check fail
96 }
97
98 return 0; // CRC check ok
99 }
100