• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <boot_upg_check.h>
17 #include <boot_upg_check_secure.h>
18 #include <boot_upg_start_up.h>
19 
boot_upg_check_image_id(hi_u32 image_id)20 hi_u32 boot_upg_check_image_id(hi_u32 image_id)
21 {
22     if (image_id != PRODUCT_UPG_FILE_IMAGE_ID) {
23         boot_msg1("check image id fail:", image_id);
24         return HI_ERR_UPG_IMAGE_ID;
25     }
26     return HI_ERR_SUCCESS;
27 }
28 
boot_upg_check_file_type(hi_u8 file_type)29 hi_u32 boot_upg_check_file_type(hi_u8 file_type)
30 {
31     if (file_type != HI_UPG_FILE_KERNEL) {
32         boot_msg1("check file type fail:", file_type);
33         return HI_ERR_UPG_FILE_TYPE;
34     }
35     return HI_ERR_SUCCESS;
36 }
37 
boot_upg_get_efuse_code_ver(hi_u8 * version)38 hi_u32 boot_upg_get_efuse_code_ver(hi_u8 *version)
39 {
40     hi_u8 pos;
41     hi_u8 efuse_data[KERNEL_VER_LEN];
42     hi_u32 ret;
43     hi_u32 check_sum = (uintptr_t)efuse_data ^ KERNEL_VER_LEN ^ 0xFF ^ KERNEL_VER_LEN;
44     (hi_void) memset_s(efuse_data, KERNEL_VER_LEN, 0xFF, KERNEL_VER_LEN, check_sum);
45     ret = hi_efuse_read(HI_EFUSE_TEE_KERNEL_VER_RW_ID, efuse_data, sizeof(efuse_data));
46     if (ret != HI_ERR_SUCCESS) {
47         return ret;
48     }
49 
50     for (pos = 0; pos < KERELN_VER_MAX; pos++) {
51         if (boot_upg_tool_bit_test(efuse_data, pos) == HI_FALSE) {
52             break;
53         }
54     }
55     if (pos >= KERELN_VER_MAX) {
56         *version = KERELN_VER_MAX;
57     } else {
58         *version = pos;
59     }
60     return ret;
61 }
62 
boot_upg_check_code_ver(hi_u8 ver)63 hi_u32 boot_upg_check_code_ver(hi_u8 ver)
64 {
65     hi_u8 current_ver;
66     hi_u32 ret = boot_upg_get_efuse_code_ver(&current_ver);
67     if (ret != HI_ERR_SUCCESS) {
68         boot_msg1("get code ver fail:", ret);
69         return ret;
70     }
71     if (ver < current_ver) {
72         ret = HI_ERR_UPG_KERNEL_VER;
73         boot_msg2("cur-filever:", current_ver, ver);
74     }
75     return ret;
76 }
77 
boot_upg_get_max_file_len(hi_u32 * file_len)78 hi_u32 boot_upg_get_max_file_len(hi_u32 *file_len)
79 {
80     hi_flash_partition_table *partition = hi_get_partition_table();
81     hi_u32 kernel_a_size = partition->table[HI_FLASH_PARTITON_KERNEL_A].size;
82     hi_u32 kernel_b_size = partition->table[HI_FLASH_PARTITON_KERNEL_B].size;
83 
84 #ifdef CONFIG_FACTORY_TEST_SUPPORT
85     /* factory mode use fix factory bin size */
86     hi_nv_ftm_factory_mode factory_mode_cfg = {0};
87     hi_u32 ret = hi_factory_nv_read(HI_NV_FTM_FACTORY_MODE, &factory_mode_cfg, sizeof(hi_nv_ftm_factory_mode), 0);
88     if (ret != HI_ERR_SUCCESS) {
89         boot_msg0("read ftm err");
90         return HI_ERR_FAILURE;
91     } else {
92         if (factory_mode_cfg.factory_mode == 0x1) {
93             *file_len = factory_mode_cfg.factory_size;
94             return HI_ERR_SUCCESS;
95         }
96     }
97 #endif
98 
99 #if defined(CONFIG_COMPRESSION_OTA_SUPPORT)
100     *file_len = kernel_a_size + kernel_b_size;
101 #else
102     hi_nv_ftm_startup_cfg *cfg = boot_upg_get_cfg();
103 
104     if (cfg->addr_start == partition->table[HI_FLASH_PARTITON_KERNEL_A].addr) {
105         *file_len = kernel_a_size;
106     } else if (cfg->addr_start == partition->table[HI_FLASH_PARTITON_KERNEL_B].addr) {
107         *file_len = kernel_b_size;
108     } else {
109         *file_len = hi_max(kernel_a_size, kernel_b_size);
110         boot_msg1("addr_start err", cfg->addr_start);
111     }
112 #endif
113     return HI_ERR_SUCCESS;
114 }
115 
boot_upg_check_code_file_len(hi_u32 file_len)116 hi_u32 boot_upg_check_code_file_len(hi_u32 file_len)
117 {
118     hi_u32 max_len;
119     hi_u32 ret = boot_upg_get_max_file_len(&max_len);
120     if (ret != HI_ERR_SUCCESS) {
121         boot_msg1("get max file len fail:", ret);
122         return ret;
123     }
124 
125     if (file_len > max_len) {
126         boot_msg2("filelen>maxlen:", file_len, max_len);
127         return HI_ERR_UPG_FILE_LEN_OVER;
128     }
129     return HI_ERR_SUCCESS;
130 }
131 
boot_upg_get_common_head(hi_u32 addr,hi_upg_common_head * head)132 hi_u32 boot_upg_get_common_head(hi_u32 addr, hi_upg_common_head *head)
133 {
134     hi_u32 ret = hi_flash_read(addr, sizeof(hi_upg_common_head), (hi_u8 *)head);
135     if (ret != HI_ERR_SUCCESS) {
136         return ret;
137     }
138 
139     return ret;
140 }
141 
boot_upg_get_section_head(hi_u32 addr,hi_upg_section_head * section_head)142 hi_u32 boot_upg_get_section_head(hi_u32 addr, hi_upg_section_head *section_head)
143 {
144     hi_upg_common_head head = { 0 };
145     hi_u32 ret;
146 
147     if (section_head == HI_NULL) {
148         return HI_ERR_UPG_NULL_POINTER;
149     }
150     ret = hi_flash_read(addr, sizeof(hi_upg_common_head), (hi_u8 *)(&head));
151     if (ret != HI_ERR_SUCCESS) {
152         return ret;
153     }
154     ret = hi_flash_read(addr + head.section_offset, sizeof(hi_upg_section_head), (hi_u8 *)section_head);
155     if (ret != HI_ERR_SUCCESS) {
156         return ret;
157     }
158 
159     return ret;
160 }
161 
boot_upg_check_alg_param(const hi_upg_common_head * head)162 hi_u32 boot_upg_check_alg_param(const hi_upg_common_head *head)
163 {
164     sign_alg_param alg_param;
165     hi_u32 cs = (uintptr_t)(&alg_param) ^ sizeof(sign_alg_param) ^
166                 (uintptr_t)(&(head->param)) ^ sizeof(sign_alg_param);
167     if (memcpy_s(&alg_param, sizeof(sign_alg_param), &(head->param), sizeof(sign_alg_param), cs) != EOK) {
168         return HI_ERR_FAILURE;
169     }
170     if ((alg_param.sign_alg != HI_MODE_PKCS_V15) && (alg_param.sign_alg != HI_MODE_PKCS_PSS) &&
171         (alg_param.sign_alg != HI_MODE_ECC)) {
172         return HI_ERR_UPG_SIGN_ALG;
173     }
174     if (alg_param.sign_alg < HI_MODE_ECC) {
175         if (head->key_len != sizeof(upg_rsa_key)) {
176             return HI_ERR_UPG_RSA_KEY_LEN;
177         }
178         if (head->section_offset != (sizeof(hi_upg_common_head) + head->key_len + sizeof(upg_rsa_sign))) {
179             return HI_ERR_UPG_RSA_HEAD_SIGN;
180         }
181         return HI_ERR_SUCCESS;
182     }
183     if (head->key_len != sizeof(upg_ecc_key)) {
184         return HI_ERR_UPG_ECC_KEY_LEN;
185     }
186     if (head->section_offset != (sizeof(hi_upg_common_head) + head->key_len + sizeof(upg_ecc_sign))) {
187         return HI_ERR_UPG_ECC_HEAD_SIGN;
188     }
189     return HI_ERR_SUCCESS;
190 }
191 
boot_upg_check_common_head(const hi_upg_common_head * head)192 hi_u32 boot_upg_check_common_head(const hi_upg_common_head *head)
193 {
194     hi_u32 ret = boot_upg_check_image_id(head->image_id);
195     if (ret != HI_ERR_SUCCESS) {
196         return ret;
197     }
198     ret = boot_upg_check_file_type(head->file_type);
199     if (ret != HI_ERR_SUCCESS) {
200         return ret;
201     }
202     ret = boot_upg_check_code_file_len(head->file_len);
203     if (ret != HI_ERR_SUCCESS) {
204         return ret;
205     }
206     if ((head->file_len != (head->section_offset + head->section_len)) ||
207         (head->section_offset != (sizeof(hi_upg_common_head) + sizeof(hi_upg_key) + sizeof(hi_upg_sign))) ||
208         (head->section_len < (sizeof(hi_upg_section_head) + sizeof(upg_rsa_sign)))) {
209         return HI_ERR_UPG_FILE_LEN;
210     }
211     if (boot_upg_is_secure_efuse() != HI_TRUE) {
212         return HI_ERR_SUCCESS;
213     }
214     ret = boot_upg_check_code_ver(head->file_version);
215     if (ret != HI_ERR_SUCCESS) {
216         return ret;
217     }
218     return boot_upg_check_alg_param(head);
219 }
220 
boot_upg_check_file(hi_u32 flash_addr)221 hi_u32 boot_upg_check_file(hi_u32 flash_addr)
222 {
223     hi_u32 ret = HI_ERR_UPG_MALLOC_FAIL;
224     hi_upg_head *upg_head = (hi_upg_head *)boot_malloc(sizeof(hi_upg_head));
225 
226     if (upg_head == HI_NULL) {
227         goto end;
228     }
229     ret = hi_flash_read(flash_addr, sizeof(hi_upg_head), (hi_u8 *)upg_head);
230     if (ret != HI_ERR_SUCCESS) {
231         goto end;
232     }
233     hi_upg_common_head *common_head = &(upg_head->common);
234     ret = boot_upg_check_common_head(common_head);
235     if (ret != HI_ERR_SUCCESS) {
236         goto end;
237     }
238 
239     ret = hi_cipher_init();
240     if (ret != HI_ERR_SUCCESS) {
241         goto end;
242     }
243     if (boot_upg_is_secure_efuse() == HI_TRUE) {
244         ret = boot_upg_check_secure_info(flash_addr, upg_head);
245     } else {
246         ret = boot_upg_check_unsecure_info(flash_addr, upg_head);
247     }
248     hi_u32 ck = hi_cipher_deinit();
249     if (ret == HI_ERR_SUCCESS) {
250         ret = ck;
251     }
252 end:
253     boot_upg_mem_free(upg_head);
254     return ret;
255 }
256 
boot_get_start_addr_offset(hi_u32 addr,hi_u32 * offset)257 hi_void boot_get_start_addr_offset(hi_u32 addr, hi_u32 *offset)
258 {
259     hi_upg_section_head section_head = { 0 };
260     hi_u32 ret = boot_upg_get_section_head(addr, &section_head);
261     if (ret == HI_ERR_SUCCESS) {
262         *offset = addr + section_head.section0_offset;
263     } else {
264         boot_msg1("get addr offset fail:", ret);
265         *offset = addr;
266     }
267 }
268 
269