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(¤t_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, §ion_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