• 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  * 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