• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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