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 * Description: UPG factory mode c file
15 */
16
17 #include "factory.h"
18 #include <stddef.h>
19 #include <stdint.h>
20 #include "securec.h"
21 #include "common_def.h"
22 #include "memory_config_common.h"
23 #include "sfc.h"
24 #ifndef WS63_PRODUCT_NONE
25 #include "osal_addr.h"
26 #else
27 #include "secure_verify_boot.h"
28 #endif
29 #ifdef CONFIG_MIDDLEWARE_SUPPORT_NV
30 #include "nv.h"
31 #endif
32
mfg_malloc(uint32_t size)33 static void *mfg_malloc(uint32_t size)
34 {
35 void *tmp_ptr = NULL;
36 #ifndef WS63_PRODUCT_NONE
37 tmp_ptr = osal_kmalloc(size, 0);
38 #else
39 uint32_t irq = global_interrupt_lock();
40 tmp_ptr = malloc(size);
41 global_interrupt_restore(irq);
42 #endif
43 return tmp_ptr;
44 }
45
mfg_free(void * addr)46 static void mfg_free(void *addr)
47 {
48 #ifndef WS63_PRODUCT_NONE
49 osal_kfree(addr);
50 #else
51 uint32_t irq = global_interrupt_lock();
52 free(addr);
53 global_interrupt_restore(irq);
54 #endif
55 }
56
check_factory_addr(uint32_t addr,uint32_t size)57 static errcode_t check_factory_addr(uint32_t addr, uint32_t size)
58 {
59 if ((addr > FLASH_MAPPED_END) || ((addr + size) > FLASH_MAPPED_END)) {
60 return ERRCODE_FAIL;
61 }
62 return ERRCODE_SUCC;
63 }
64
mfg_flash_erase_etc(const uint32_t flash_offset,const uint32_t size)65 static errcode_t mfg_flash_erase_etc(const uint32_t flash_offset, const uint32_t size)
66 {
67 errcode_t ret = ERRCODE_FAIL;
68 // 地址向前4K对齐,大小向上4K补齐
69 uint32_t end_addr = flash_offset + size;
70 uint32_t start_sector = flash_offset & ~BYTE_4K_MASK;
71 uint32_t end_sector = (end_addr & BYTE_4K_MASK) == 0 ? end_addr : (end_addr & ~BYTE_4K_MASK) + BYTE_4K;
72 uint32_t hal_erase_size = end_sector - start_sector;
73 uint32_t pre_size = flash_offset - start_sector;
74 uint32_t last_size = end_sector - end_addr;
75
76 uint8_t *writeback_pre_data = mfg_malloc(BYTE_4K);
77 if (writeback_pre_data == NULL) {
78 return ERRCODE_MALLOC;
79 }
80 uint8_t *writeback_last_data = mfg_malloc(BYTE_4K);
81 if (writeback_last_data == NULL) {
82 mfg_free(writeback_pre_data);
83 return ERRCODE_MALLOC;
84 }
85 if (pre_size != 0) {
86 ret = uapi_sfc_reg_read(start_sector, writeback_pre_data, pre_size);
87 if (ret != ERRCODE_SUCC) {
88 goto end;
89 }
90 }
91 if (last_size != 0) {
92 ret = uapi_sfc_reg_read(end_addr, writeback_last_data, last_size);
93 if (ret != ERRCODE_SUCC) {
94 goto end;
95 }
96 }
97 // 擦除
98 ret = uapi_sfc_reg_erase(start_sector, hal_erase_size);
99 if (ret != ERRCODE_SUCC) {
100 goto end;
101 }
102 // 回写
103 if (pre_size != 0) {
104 ret = mfg_flash_write_info(writeback_pre_data, start_sector, pre_size, false);
105 if (ret != ERRCODE_SUCC) {
106 goto end;
107 }
108 }
109 if (last_size != 0) {
110 ret = mfg_flash_write_info(writeback_last_data, end_addr, last_size, false);
111 if (ret != ERRCODE_SUCC) {
112 goto end;
113 }
114 }
115 end:
116 mfg_free(writeback_pre_data);
117 mfg_free(writeback_last_data);
118 return ret;
119 }
120
mfg_flash_erase(void)121 errcode_t mfg_flash_erase(void)
122 {
123 errcode_t ret = ERRCODE_FAIL;
124 partition_information_t img_info;
125
126 memset_s(&img_info, sizeof(img_info), 0, sizeof(img_info));
127 ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &img_info);
128 if (ret != ERRCODE_SUCC) {
129 return ret;
130 }
131 uint32_t factory_bin_addr = img_info.part_info.addr_info.addr;
132 uint32_t single_size = img_info.part_info.addr_info.size - (MFG_FACTORY_REGION_CONFIG_SIZE * FACTORY_INFO_OFFSET);
133
134 ret = check_factory_addr(factory_bin_addr, single_size);
135 if (ret != ERRCODE_SUCC) {
136 return ret;
137 }
138 ret = uapi_sfc_reg_erase(factory_bin_addr, single_size);
139 if (ret != ERRCODE_SUCC) {
140 return ret;
141 }
142 return ERRCODE_SUCC;
143 }
144
mfg_flash_read(uint8_t * ram_data,const uint32_t size)145 errcode_t mfg_flash_read(uint8_t *ram_data, const uint32_t size)
146 {
147 errcode_t ret = ERRCODE_FAIL;
148 partition_information_t img_info;
149
150 memset_s(&img_info, sizeof(img_info), 0, sizeof(img_info));
151 ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &img_info);
152 if (ret != ERRCODE_SUCC) {
153 return ret;
154 }
155 uint32_t factory_info_addr = img_info.part_info.addr_info.addr +
156 img_info.part_info.addr_info.size - (MFG_FACTORY_REGION_CONFIG_SIZE * FACTORY_INFO_OFFSET);
157 ret = check_factory_addr(factory_info_addr, size);
158 if (ret != ERRCODE_SUCC) {
159 return ret;
160 }
161 return uapi_sfc_reg_read(factory_info_addr, ram_data, size);
162 }
163
mfg_flash_check_erase(const uint32_t flash_offset,uint32_t size,bool do_erase)164 static errcode_t mfg_flash_check_erase(const uint32_t flash_offset, uint32_t size, bool do_erase)
165 {
166 errcode_t ret = ERRCODE_FAIL;
167 if (do_erase == true) {
168 ret = mfg_flash_erase_etc(flash_offset, size);
169 if (ret != ERRCODE_SUCC) {
170 return ret;
171 }
172 }
173 return ERRCODE_SUCC;
174 }
175
mfg_flash_write_info(const uint8_t * ram_data,uint32_t flash_offset,uint32_t size,bool do_erase)176 errcode_t mfg_flash_write_info(const uint8_t *ram_data, uint32_t flash_offset, uint32_t size, bool do_erase)
177 {
178 errcode_t ret = ERRCODE_FAIL;
179 uint32_t bus_read_addr = flash_offset + FLASH_START;
180 ret = mfg_flash_check_erase(flash_offset, size, do_erase);
181 if (ret != ERRCODE_SUCC) {
182 return ret;
183 }
184 uint8_t *cmp_data = mfg_malloc(size);
185 if (cmp_data == NULL) {
186 return ERRCODE_MALLOC;
187 }
188 ret = uapi_sfc_reg_write(flash_offset, (uint8_t *)ram_data, size);
189 if (ret != ERRCODE_SUCC) {
190 goto write_failed;
191 }
192 /* 回读比较 */
193 ret = (errcode_t)memcpy_s(cmp_data, size, (uint8_t *)(uintptr_t)bus_read_addr, size);
194 if (ret != EOK) {
195 goto write_failed;
196 }
197 ret = (errcode_t)memcmp(cmp_data, ram_data, size);
198 if (ret != EOK) {
199 goto write_failed;
200 }
201 write_failed:
202 mfg_free(cmp_data);
203 return ret;
204 }
205
mfg_flash_write(const uint8_t * ram_data,uint32_t size)206 errcode_t mfg_flash_write(const uint8_t *ram_data, uint32_t size)
207 {
208 errcode_t ret = ERRCODE_FAIL;
209 partition_information_t img_info;
210
211 memset_s(&img_info, sizeof(img_info), 0, sizeof(img_info));
212 ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &img_info);
213 if (ret != ERRCODE_SUCC) {
214 return ret;
215 }
216 uint32_t flash_offset = img_info.part_info.addr_info.addr + img_info.part_info.addr_info.size -
217 (MFG_FACTORY_REGION_CONFIG_SIZE * FACTORY_INFO_OFFSET);
218
219 ret = check_factory_addr(flash_offset, size);
220 if (ret != ERRCODE_SUCC) {
221 return ret;
222 }
223 return mfg_flash_write_info(ram_data, flash_offset, size, true);
224 }
225
mfg_get_region_config(mfg_region_config_t * region_cfg)226 uint32_t mfg_get_region_config(mfg_region_config_t *region_cfg)
227 {
228 errcode_t ret = ERRCODE_FAIL;
229
230 ret = uapi_partition_init();
231 if (ret != ERRCODE_SUCC) {
232 return ret;
233 }
234
235 ret |= uapi_partition_get_info(PARTITION_APP_IMAGE, &(region_cfg->app_info));
236 ret |= uapi_partition_get_info(PARTITION_FOTA_DATA, &(region_cfg->mfg_info));
237 return ret;
238 }
239
240 #ifdef WS63_PRODUCT_NONE
mfg_get_ftm_config_init(const partition_information_t * img_info)241 static uint32_t mfg_get_ftm_config_init(const partition_information_t *img_info)
242 {
243 errcode_t ret;
244 uint32_t factory_addr = img_info->part_info.addr_info.addr + FLASH_START;
245
246 image_code_info_t *image_code_info = (image_code_info_t *)(uintptr_t)(factory_addr + sizeof(image_key_area_t));
247 uint32_t single_size = image_code_info->code_area_len + IMAGE_HEADER_LEN;
248
249 mfg_factory_config_t mfg_ftm_cfg = {
250 .factory_mode = MFG_FACTORY_DEFAULT_MODE,
251 .factory_addr_start = factory_addr,
252 .factory_addr_switch = img_info->part_info.addr_info.addr + FLASH_START,
253 .factory_size = single_size,
254 .factory_switch_size = single_size,
255 .factory_valid = MFG_FACTORY_VALID,
256 .check_num = MFG_FACTORY_CONFIG_CHECK
257 };
258 ret = check_factory_addr((mfg_ftm_cfg.factory_addr_start - FLASH_START), single_size);
259 if (ret != ERRCODE_SUCC) {
260 return ret;
261 }
262 ret = mfg_flash_write((const uint8_t *)(&mfg_ftm_cfg), sizeof(mfg_factory_config_t));
263 if (ret != ERRCODE_SUCC) {
264 return ERRCODE_FAIL;
265 }
266 return ERRCODE_SUCC;
267 }
268
269 /**
270 * @brief 获取当前运行的镜像分区。
271 * @return 成功返回分区序号,失败 默认从A区启动。
272 */
mfg_get_ftm_run_region(mfg_factory_config_t * mfg_factory_cfg)273 uint32_t mfg_get_ftm_run_region(mfg_factory_config_t *mfg_factory_cfg)
274 {
275 errcode_t ret;
276 partition_information_t img_info = {0};
277 uint32_t factory_addr = 0;
278
279 if (mfg_factory_cfg == NULL) {
280 return FTM_REGION_SERVICE;
281 }
282 ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &img_info);
283 if (ret != ERRCODE_SUCC) {
284 return FTM_REGION_SERVICE;
285 }
286 ret = mfg_flash_read((uint8_t *)mfg_factory_cfg, sizeof(mfg_factory_config_t));
287 if (ret != ERRCODE_SUCC) {
288 return FTM_REGION_SERVICE;
289 }
290
291 factory_addr = img_info.part_info.addr_info.addr + FLASH_START;
292 image_key_area_t *image_code_info = (image_key_area_t *)(factory_addr);
293 if (mfg_factory_cfg->check_num != MFG_FACTORY_CONFIG_CHECK &&
294 image_code_info->image_id == FACTORYBOOT_KEY_AREA_IMAGE_ID &&
295 image_code_info->structure_length == sizeof(image_key_area_t)) {
296 if (mfg_get_ftm_config_init(&img_info) != ERRCODE_SUCC) {
297 return FTM_REGION_SERVICE;
298 }
299 }
300
301 ret = mfg_flash_read((uint8_t *)mfg_factory_cfg, sizeof(mfg_factory_config_t));
302 if (ret != ERRCODE_SUCC) {
303 return FTM_REGION_SERVICE;
304 }
305 if (mfg_factory_cfg->factory_mode != FTM_REGION_SERVICE && mfg_factory_cfg->factory_mode != FTM_REGION_FACTORY) {
306 return FTM_REGION_SERVICE;
307 }
308 return mfg_factory_cfg->factory_mode;
309 }
310 #endif
311
mfg_factory_mode_switch(mfg_region_config_t img_info,uint32_t switch_mode,mfg_factory_config_t * config)312 errcode_t mfg_factory_mode_switch(mfg_region_config_t img_info, uint32_t switch_mode, mfg_factory_config_t *config)
313 {
314 if (config->factory_valid == MFG_FACTORY_INVALID) {
315 return ERRCODE_FAIL;
316 }
317 if (switch_mode == 0x0) { /* switch to normal mode */
318 if (config->factory_mode != 0x0) {
319 config->factory_mode = 0x0;
320 config->factory_valid = MFG_FACTORY_INVALID;
321 config->factory_addr_switch = img_info.app_info.part_info.addr_info.addr + FLASH_START;
322 config->factory_switch_size = img_info.app_info.part_info.addr_info.size;
323 /* nv backup */
324 #ifdef CONFIG_MIDDLEWARE_SUPPORT_NV
325 nv_backup_mode_t backup_flag = {0};
326 for (uint32_t i = 0; i < KEY_ID_REGION_MAX_NUM; i++) {
327 backup_flag.region_mode[i] = 1;
328 }
329 errcode_t nv_ret = uapi_nv_backup((const nv_backup_mode_t *)&backup_flag);
330 if (nv_ret != ERRCODE_SUCC) {
331 return nv_ret;
332 }
333 #endif
334 }
335 } else {
336 return ERRCODE_FAIL;
337 }
338 return check_factory_addr((config->factory_addr_switch - FLASH_START), config->factory_switch_size);
339 }
340
341 #ifdef _PRE_WLAN_FEATURE_MFG_TEST
plt_flash_read_data(uint32_t addr,uint32_t size,uint8_t * data)342 errcode_t plt_flash_read_data(uint32_t addr, uint32_t size, uint8_t *data)
343 {
344 errcode_t ret;
345
346 ret = check_factory_addr((addr - FLASH_START), size);
347 if (ret != ERRCODE_SUCC) {
348 return ERRCODE_FAIL;
349 }
350
351 return uapi_sfc_reg_read((addr - FLASH_START), data, size);
352 }
353
plt_flash_write_data(uint32_t addr,uint32_t size,uint8_t * data,uint32_t * left)354 errcode_t plt_flash_write_data(uint32_t addr, uint32_t size, uint8_t *data, uint32_t *left)
355 {
356 errcode_t ret;
357 partition_information_t img_info = {0};
358 uint32_t info_addr = 0;
359 uint32_t index = 0;
360 uint32_t length = 0;
361 uint32_t flash_block_rec[FLASH_PRIVATE_CUSTOM_CONFIG_TIMES] = {0};
362
363 // 校验地址范围
364 ret = check_factory_addr((addr - FLASH_START), size);
365 if (ret != ERRCODE_SUCC) {
366 return ERRCODE_FAIL;
367 }
368
369 ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &img_info);
370 if (ret != ERRCODE_SUCC) {
371 return ret;
372 }
373 info_addr = img_info.part_info.addr_info.addr + img_info.part_info.addr_info.size -
374 (MFG_FACTORY_REGION_CONFIG_SIZE * FACTORY_INFO_OFFSET) + FLASH_PRIVATE_CUSTOM_CONFIG_OFFSET;
375 ret = uapi_sfc_reg_read(info_addr, (uint8_t *)flash_block_rec, sizeof(flash_block_rec));
376 if (ret != ERRCODE_SUCC) {
377 return ERRCODE_FAIL;
378 }
379 for (index = 0; index < (sizeof(flash_block_rec) / sizeof(uint32_t)); ++index) {
380 if (flash_block_rec[index] == 0xFFFFFFFF) {
381 flash_block_rec[index] = length + size;
382 addr += length;
383 ret = uapi_sfc_reg_write(info_addr, (uint8_t *)flash_block_rec, sizeof(flash_block_rec));
384 if (ret != ERRCODE_SUCC) {
385 return ret;
386 }
387 *left = (FLASH_PRIVATE_CUSTOM_CONFIG_TIMES - index - 1);
388 break;
389 }
390 length = flash_block_rec[index];
391 }
392 return uapi_sfc_reg_write((addr - FLASH_START), data, size);
393 }
394 #endif
395