• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Bestechnic (Shanghai) Co., Ltd. All rights reserved.
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 #include <string.h>
16 #include <stdlib.h>
17 #include "flash.h"
18 #include "cmsis_os.h"
19 #include "cmsis_os2.h"
20 #include "hal_trace.h"
21 #include "hal_norflash.h"
22 #include "hal_cache.h"
23 #include "hal_cmu.h"
24 #include "cmsis.h"
25 #include "pmu.h"
26 #include "crc32_c.h"
27 
28 #if BES_HAL_DEBUG
29 #define ENTER_FUNCTION() printf("%s enter ->\n", __FUNCTION__)
30 #define LEAVE_FUNCTION() printf("%s <- leave\n", __FUNCTION__)
31 #define FOOTPRINT() printf("%s:%d\n", __FUNCTION__, __LINE__)
32 #define TRACEME(str, ...) printf("%s:%d " str, __FUNCTION__, __LINE__, ##__VA_ARGS__)
33 #else
34 #define ENTER_FUNCTION()
35 #define LEAVE_FUNCTION()
36 #define FOOTPRINT()
37 #define TRACEME(str, ...)
38 #endif
39 #define FAIL_FUNCTION() printf("%s:%d fail!\n", __FUNCTION__, __LINE__)
40 
41 #define FLASH_PAGE_SIZE_IN_BYTES 256
42 #define OTA_MALLOC_BUF_SIZE FLASH_BLOCK_SIZE_IN_BYTES
43 #define ONE_BLOCK_SIZE (64 * 1024)
44 #define BLOCK_MAX_INFO 40
45 #define RW_MAX_BLOCK 13
46 #define RW_MAX_PARTITION 3
47 #define MAX_FLASH_OPTIONS 3
48 extern const hal_logic_partition_t g_halPartitions[];
49 
50 static bootinfo_zone cur_bootinfo_zone = BOOTINFO_ZONE_MAX;
51 static bootinfo_zone cur_bootinfoBK_zone = BOOTINFO_ZONE_MAX;
52 
53 enum FLASH_OPTIONS {
54     FLASH_READ = 0,
55     FLASH_WRITE = 1,
56     FLASH_ERASE = 2,
57 };
58 
59 struct RW_BLOCK_INFO {
60     bool flag;
61     uint32_t blocknum;
62     uint64_t count[MAX_FLASH_OPTIONS];
63 };
64 
65 struct HAL_FLASH_BAD_INFO {
66     bool flag;
67     enum FLASH_OPTIONS option;
68     hal_partition_t partition;
69     uint32_t offset;
70     uint32_t blocknum;
71 };
72 
73 struct HAL_FLASH_RW_INFO {
74     hal_partition_t partition;
75     struct RW_BLOCK_INFO blockInfo[RW_MAX_BLOCK];
76 };
77 
78 typedef struct {
79     char *bin_name;
80     hal_partition_t partition;
81 } user_writeable_flash_info;
82 
83 user_writeable_flash_info user_writeable_partitions[] = {
84     {"boot", HAL_PARTITION_BOOTLOADER},
85     {"data", HAL_PARTITION_DATA},
86     {"log", HAL_PARTITION_LOG},
87     {"littlefs", HAL_PARTITION_RESOURCE},
88     {"secure", HAL_PARTITION_TRUSTZONEA},
89     {"misc", HAL_PARTITION_MISC},
90     {"factory", HAL_PARTITION_ENV},
91     {"factory_backup", HAL_PARTITION_ENV_REDUND},
92     {"system_mini", HAL_PARTITION_SYSTEM_MINI},
93 };
94 
95 struct HAL_FLASH_BAD_INFO g_flashBadInfo[BLOCK_MAX_INFO];
96 struct HAL_FLASH_BAD_INFO g_normalFlashBadInfo;
97 static bool g_rwFlashInitFlag = false;
98 struct HAL_FLASH_RW_INFO g_flashRwInfo[RW_MAX_PARTITION] = {
99     {
100         .partition = HAL_PARTITION_DATA,
101     },
102     {
103         .partition = HAL_PARTITION_LOG,
104     },
105     {
106         .partition = HAL_PARTITION_RESOURCE,
107     }};
108 
FlashOptionStructInit(void)109 static void FlashOptionStructInit(void)
110 {
111     for (size_t i = 0; i < RW_MAX_PARTITION; i++) {
112         for (size_t j = 0; j < RW_MAX_BLOCK; j++) {
113             g_flashRwInfo[i].blockInfo[j].blocknum = 0;
114             g_flashRwInfo[i].blockInfo[j].flag = false;
115             for (size_t k = 0; k < MAX_FLASH_OPTIONS; k++) {
116                 g_flashRwInfo[i].blockInfo[j].count[k] = 0;
117             }
118         }
119     }
120 
121     g_rwFlashInitFlag = true;
122 }
123 
bes_check_user_write_flash_addr(const uint32_t addr,const uint32_t size)124 int bes_check_user_write_flash_addr(const uint32_t addr, const uint32_t size)
125 {
126     hal_logic_partition_t info;
127     int32_t ret = -1;
128     int32_t index = 0;
129 
130     for (index = 0; index < sizeof(user_writeable_partitions) / sizeof(user_writeable_partitions[0]); index++) {
131         if (hal_flash_info_get(user_writeable_partitions[index].partition, &info) != 0) {
132             break;
133         }
134 
135         if ((info.partition_start_addr <= addr) && ((addr + size) <= (info.partition_start_addr + info.partition_length))) {
136             ret = 0;
137             break;
138         }
139     }
140     return ret;
141 }
142 
143 osMutexId FlashMutex = NULL;
144 osMutexDef_t os_mutex_def_flash;
FlashosMutexWait(void)145 static void FlashosMutexWait(void)
146 {
147     if (FlashMutex == NULL) {
148         FlashMutex = osMutexCreate(&os_mutex_def_flash);
149     }
150 
151     osMutexWait(FlashMutex, osWaitForever);
152 }
153 
my_memcpy(void * dst,void * src,size_t num)154 void *my_memcpy(void *dst, void *src, size_t num)
155 {
156     int offset1 = (4 - ((uint32_t)dst & 3)) & 3;
157     int offset2 = (4 - ((uint32_t)src & 3)) & 3;
158 
159     if (offset1 != offset2) {
160         return memcpy(dst, src, num);
161     }
162 
163     int wordnum = num > offset1 ? (num - offset1) / 8 : 0;
164     int slice = num > offset1 ? (num - offset1) % 8 : 0;
165     char *pdst = (char *)dst;
166     char *psrc = (char *)src;
167     long long *pintsrc = NULL;
168     long long *pintdst = NULL;
169 
170     while (offset1--) {
171         *pdst++ = *psrc++;
172     }
173 
174     pintdst = (long long *)pdst;
175     pintsrc = (long long *)psrc;
176     while (wordnum--) {
177         *pintdst++ = *pintsrc++;
178     }
179 
180     pdst = (char *)pintdst;
181     psrc = (char *)pintsrc;
182     while (slice--) {
183         *pdst++ = *psrc++;
184     }
185 
186     return dst;
187 }
188 
flash_read(const uint32_t addr,uint8_t * dst,const uint32_t size)189 int flash_read(const uint32_t addr, uint8_t *dst, const uint32_t size)
190 {
191     int ret = 0;
192     uint32_t lock = 0;
193 
194     if (dst == NULL) {
195         ret = -1;
196         goto RETURN;
197     }
198 
199     FlashosMutexWait();
200     pmu_flash_write_config();
201     lock = int_lock_global();
202     ret = NORFLASH_API_WRAP(hal_norflash_read)(HAL_FLASH_ID_0, addr, dst, size);
203     int_unlock_global(lock);
204     pmu_flash_read_config();
205     osMutexRelease(FlashMutex);
206 
207 RETURN:
208     return ret;
209 }
210 
flash_write(const uint32_t addr,const uint8_t * src,const uint32_t size)211 int flash_write(const uint32_t addr, const uint8_t *src, const uint32_t size)
212 {
213     int ret = 0;
214     uint32_t lock;
215 
216     ret = bes_check_user_write_flash_addr(addr, size);
217     if (ret) {
218         return ret;
219     }
220 
221     FlashosMutexWait();
222     pmu_flash_write_config();
223     lock = int_lock_global();
224     ret = NORFLASH_API_WRAP(hal_norflash_write)(HAL_FLASH_ID_0, addr, src, size);
225     int_unlock_global(lock);
226     pmu_flash_read_config();
227     hal_cache_invalidate_all(HAL_CACHE_ID_I_CACHE);
228     osMutexRelease(FlashMutex);
229 
230     return ret;
231 }
232 
flash_erase(const uint32_t addr,const uint32_t size)233 int flash_erase(const uint32_t addr, const uint32_t size)
234 {
235     int ret = 0;
236     uint32_t lock = 0;
237 
238     ret = bes_check_user_write_flash_addr(addr, size);
239 
240     if (ret) {
241         return ret;
242     }
243 
244     FlashosMutexWait();
245     pmu_flash_write_config();
246     lock = int_lock_global();
247     ret = NORFLASH_API_WRAP(hal_norflash_erase)(HAL_FLASH_ID_0, addr, size);
248     int_unlock_global(lock);
249 
250     pmu_flash_read_config();
251     hal_cache_invalidate_all(HAL_CACHE_ID_I_CACHE);
252     osMutexRelease(FlashMutex);
253 
254     return ret;
255 }
256 
SetFlashOptionInfo(hal_partition_t partition,uint32_t size,uint32_t option)257 static int32_t SetFlashOptionInfo(hal_partition_t partition, uint32_t size, uint32_t option)
258 {
259     uint32_t blockNum;
260 
261     if (((partition != HAL_PARTITION_DATA) && (partition != HAL_PARTITION_LOG) && (partition != HAL_PARTITION_RESOURCE)) || (option >= MAX_FLASH_OPTIONS)) {
262         TRACE(0, "%s---%d----%d-----%d\r\n", __FUNCTION__, partition, size, option);
263         return -1;
264     }
265 
266     if (!g_rwFlashInitFlag) {
267         FlashOptionStructInit();
268     }
269 
270     blockNum = (size / ONE_BLOCK_SIZE);
271 
272     for (size_t i = 0; i < RW_MAX_PARTITION; i++) {
273         if (g_flashRwInfo[i].partition == partition) {
274             for (size_t j = 0; j < RW_MAX_BLOCK; j++) {
275                 if (g_flashRwInfo[i].blockInfo[j].flag) {
276                     if (g_flashRwInfo[i].blockInfo[j].blocknum == blockNum)
277                         g_flashRwInfo[i].blockInfo[j].count[option]++;
278                     else
279                         continue;
280                 } else {
281                     g_flashRwInfo[i].blockInfo[j].blocknum = blockNum;
282                     g_flashRwInfo[i].blockInfo[j].count[option]++;
283                     g_flashRwInfo[i].blockInfo[j].flag = true;
284                     break;
285                 }
286             }
287         }
288     }
289 
290     return 0;
291 }
292 
SetFlashBadOptionInfo(hal_partition_t partition,uint32_t size,uint32_t option)293 static int32_t SetFlashBadOptionInfo(hal_partition_t partition, uint32_t size, uint32_t option)
294 {
295     if (((partition != HAL_PARTITION_DATA) && (partition != HAL_PARTITION_LOG) && (partition != HAL_PARTITION_RESOURCE)) || (option >= MAX_FLASH_OPTIONS)) {
296         return -1;
297     }
298 
299     struct HAL_FLASH_BAD_INFO *flashBadInfo = &g_normalFlashBadInfo;
300     flashBadInfo->option = option;
301     flashBadInfo->partition = partition;
302 
303     if ((size % ONE_BLOCK_SIZE) > 0) {
304         flashBadInfo->blocknum = (size / ONE_BLOCK_SIZE) + 1;
305     } else {
306         flashBadInfo->blocknum = (size / ONE_BLOCK_SIZE);
307     }
308 
309     for (size_t i = 0; i < BLOCK_MAX_INFO; i++) {
310         if (g_flashBadInfo[i].flag) {
311             continue;
312         }
313 
314         g_flashBadInfo[i] = g_normalFlashBadInfo;
315         g_flashBadInfo[i].flag = true;
316     }
317 
318     return 0;
319 }
320 
GetFlashBadOptionInfo(void)321 static struct HAL_FLASH_BAD_INFO *GetFlashBadOptionInfo(void)
322 {
323     return &g_normalFlashBadInfo;
324 }
325 
326 /**
327  * Get the information of the specified flash area
328  *
329  * @param[in]  in_partition     The target flash logical partition
330  * @param[in]  partition        The buffer to store partition info
331  *
332  * @return  0: On success, otherwise is error
333  */
hal_flash_info_get(hal_partition_t in_partition,hal_logic_partition_t * partition)334 int32_t hal_flash_info_get(hal_partition_t in_partition, hal_logic_partition_t *partition)
335 {
336     hal_logic_partition_t *logic_partition;
337 
338     if (in_partition >= HAL_PARTITION_MAX || partition == NULL) {
339         return -1;
340     }
341 
342     ENTER_FUNCTION();
343     logic_partition = (hal_logic_partition_t *)&g_halPartitions[in_partition];
344     memcpy(partition, logic_partition, sizeof(hal_logic_partition_t));
345     LEAVE_FUNCTION();
346 
347     return 0;
348 }
349 
350 /**
351  * Erase an area on a Flash logical partition
352  *
353  * @note  Erase on an address will erase all data on a sector that the
354  *        address is belonged to, this function does not save data that
355  *        beyond the address area but in the affected sector, the data
356  *        will be lost.
357  *
358  * @param[in]  in_partition  The target flash logical partition which should be erased
359  * @param[in]  off_set       Start address of the erased flash area
360  * @param[in]  size          Size of the erased flash area
361  *
362  * @return  0 : On success, EIO : If an error occurred with any step
363  */
hal_flash_erase(hal_partition_t in_partition,uint32_t off_set,uint32_t size)364 int32_t hal_flash_erase(hal_partition_t in_partition, uint32_t off_set, uint32_t size)
365 {
366     uint32_t start_addr;
367     hal_logic_partition_t info;
368     int32_t ret = 0;
369 
370     ENTER_FUNCTION();
371     if (hal_flash_info_get(in_partition, &info) != 0) {
372         TRACE(0, "hal_flash_info_get fail\n");
373         ret = -1;
374         goto RETURN;
375     }
376 
377     start_addr = off_set;
378     ret = SetFlashOptionInfo(in_partition, start_addr, FLASH_ERASE);
379     if (ret < 0) {
380         TRACE(0, "SetFlashOptionInfo FAIL\r\n");
381     }
382 
383     ret = flash_erase(start_addr, size);
384     if (!ret) {
385         goto RETURN;
386     } else {
387         SetFlashBadOptionInfo(in_partition, start_addr, FLASH_ERASE);
388     }
389 
390 RETURN:
391     LEAVE_FUNCTION();
392     return ret;
393 }
394 
395 /**
396  * Write data to an area on a flash logical partition without erase
397  *
398  * @param[in]  in_partition    The target flash logical partition which should be read which should be written
399  * @param[in]  off_set         Point to the start address that the data is written to, and
400  *                             point to the last unwritten address after this function is
401  *                             returned, so you can call this function serval times without
402  *                             update this start address.
403  * @param[in]  inBuffer        point to the data buffer that will be written to flash
404  * @param[in]  inBufferLength  The length of the buffer
405  *
406  * @return  0 : On success, EIO : If an error occurred with any step
407  */
hal_flash_write(hal_partition_t in_partition,uint32_t * off_set,const void * in_buf,uint32_t in_buf_len)408 int32_t hal_flash_write(hal_partition_t in_partition, uint32_t *off_set, const void *in_buf, uint32_t in_buf_len)
409 {
410     int32_t ret = 0;
411     uint32_t start_addr;
412     uint32_t partition_end;
413     hal_logic_partition_t info;
414 
415     ENTER_FUNCTION();
416     if (hal_flash_info_get(in_partition, &info) != 0) {
417         TRACE(0, "hal_flash_info_get fail\n");
418         ret = -1;
419         goto RETURN;
420     }
421 
422     start_addr = *off_set;
423     partition_end = info.partition_start_addr + info.partition_length;
424     if (start_addr >= partition_end) {
425         TRACE(0, "flash over write\r\n");
426         ret = -1;
427         goto RETURN;
428     }
429 
430     if ((start_addr + in_buf_len) > partition_end) {
431         in_buf_len = partition_end - start_addr;
432         TRACE(0, "flash over write, new len is %d\r\n", in_buf_len);
433     }
434 
435     ret = SetFlashOptionInfo(in_partition, start_addr, FLASH_WRITE);
436     if (ret < 0) {
437         TRACE(0, "SetFlashOptionInfo FAIL\r\n");
438     }
439 
440     ret = flash_write(start_addr, in_buf, in_buf_len);
441     if (!ret) {
442         *off_set += in_buf_len;
443     } else {
444         SetFlashBadOptionInfo(in_partition, start_addr, FLASH_WRITE);
445     }
446 
447 RETURN:
448     LEAVE_FUNCTION();
449     return ret;
450 }
451 
452 /**
453  * Write data to an area on a flash logical partition with erase first
454  *
455  * @param[in]  in_partition    The target flash logical partition which should be read which should be written
456  * @param[in]  off_set         Point to the start address that the data is written to, and
457  *                             point to the last unwritten address after this function is
458  *                             returned, so you can call this function serval times without
459  *                             update this start address.
460  * @param[in]  inBuffer        point to the data buffer that will be written to flash
461  * @param[in]  inBufferLength  The length of the buffer
462  *
463  * @return  0 : On success, EIO : If an error occurred with any step
464  */
hal_flash_erase_write(hal_partition_t in_partition,uint32_t * off_set,const void * in_buf,uint32_t in_buf_len)465 int32_t hal_flash_erase_write(hal_partition_t in_partition, uint32_t *off_set, const void *in_buf, uint32_t in_buf_len)
466 {
467     int32_t ret = 0;
468     uint32_t start_addr;
469     uint32_t partition_end;
470     hal_logic_partition_t info;
471 
472     ENTER_FUNCTION();
473     if (hal_flash_info_get(in_partition, &info) != 0) {
474         TRACE(0, "hal_flash_info_get fail\n");
475         ret = -1;
476         goto RETURN;
477     }
478 
479     start_addr = *off_set;
480     partition_end = info.partition_start_addr + info.partition_length;
481 
482     if (start_addr >= partition_end) {
483         TRACE(0, "flash over write\r\n");
484         ret = -1;
485         goto RETURN;
486     }
487 
488     if ((start_addr + in_buf_len) > partition_end) {
489         in_buf_len = partition_end - start_addr;
490         TRACE(0, "flash over write, new len is %d\r\n", in_buf_len);
491     }
492 
493     ret = SetFlashOptionInfo(in_partition, start_addr, FLASH_ERASE);
494     if (ret < 0) {
495         TRACE(0, "SetFlashOptionInfo FAIL\r\n");
496     }
497 
498     ret = flash_erase(start_addr, in_buf_len);
499     if (ret) {
500         TRACE(0, "flash erase fail\r\n");
501         ret = -1;
502         SetFlashBadOptionInfo(in_partition, start_addr, FLASH_ERASE);
503         goto RETURN;
504     }
505 
506     ret = SetFlashOptionInfo(in_partition, start_addr, FLASH_WRITE);
507     if (ret < 0) {
508         TRACE(0, "SetFlashOptionInfo FAIL\r\n");
509     }
510 
511     ret = flash_write(start_addr, in_buf, in_buf_len);
512     if (!ret) {
513         *off_set += in_buf_len;
514     } else {
515         SetFlashBadOptionInfo(in_partition, start_addr, FLASH_WRITE);
516     }
517 
518 RETURN:
519     LEAVE_FUNCTION();
520     return ret;
521 }
522 
523 /**
524  * Read data from an area on a Flash to data buffer in RAM
525  *
526  * @param[in]  in_partition    The target flash logical partition which should be read
527  * @param[in]  off_set         Point to the start address that the data is read, and
528  *                             point to the last unread address after this function is
529  *                             returned, so you can call this function serval times without
530  *                             update this start address.
531  * @param[in]  outBuffer       Point to the data buffer that stores the data read from flash
532  * @param[in]  inBufferLength  The length of the buffer
533  *
534  * @return  0 : On success, EIO : If an error occurred with any step
535  */
hal_flash_read(hal_partition_t in_partition,uint32_t * off_set,void * out_buf,uint32_t in_buf_len)536 int32_t hal_flash_read(hal_partition_t in_partition, uint32_t *off_set, void *out_buf, uint32_t in_buf_len)
537 {
538     int32_t ret = 0;
539     uint32_t start_addr;
540     hal_logic_partition_t info;
541 
542     ENTER_FUNCTION();
543     if (hal_flash_info_get(in_partition, &info) != 0) {
544         TRACE(0, "hal_flash_info_get fail\n");
545         ret = -1;
546         goto RETURN;
547     }
548 
549     start_addr = *off_set;
550     ret = SetFlashOptionInfo(in_partition, start_addr, FLASH_READ);
551     if (ret < 0) {
552         TRACE(0, "SetFlashOptionInfo FAIL\r\n");
553     }
554 
555     ret = flash_read(start_addr, out_buf, in_buf_len);
556     if (!ret) {
557         goto RETURN;
558     } else {
559         SetFlashBadOptionInfo(in_partition, start_addr, FLASH_READ);
560     }
561 
562 RETURN:
563     LEAVE_FUNCTION();
564     return ret;
565 }
566 
567 /**
568  * Set security options on a logical partition
569  *
570  * @param[in]  partition  The target flash logical partition
571  * @param[in]  offset     Point to the start address that the data is read, and
572  *                        point to the last unread address after this function is
573  *                        returned, so you can call this function serval times without
574  *                        update this start address.
575  * @param[in]  size       Size of enabled flash area
576  *
577  * @return  0 : On success, EIO : If an error occurred with any step
578  */
hal_flash_enable_secure(hal_partition_t partition,uint32_t off_set,uint32_t size)579 int32_t hal_flash_enable_secure(hal_partition_t partition, uint32_t off_set, uint32_t size)
580 {
581     FAIL_FUNCTION();
582     return 0;
583 }
584 
585 /**
586  * Disable security options on a logical partition
587  *
588  * @param[in]  partition  The target flash logical partition
589  * @param[in]  offset     Point to the start address that the data is read, and
590  *                        point to the last unread address after this function is
591  *                        returned, so you can call this function serval times without
592  *                        update this start address.
593  * @param[in]  size       Size of disabled flash area
594  *
595  * @return  0 : On success, EIO : If an error occurred with any step
596  */
hal_flash_dis_secure(hal_partition_t partition,uint32_t off_set,uint32_t size)597 int32_t hal_flash_dis_secure(hal_partition_t partition, uint32_t off_set, uint32_t size)
598 {
599     FAIL_FUNCTION();
600     return 0;
601 }
602 
603 /**
604  * Convert physical address to logic partition id and offset in partition
605  *
606  * @param[out]  in_partition Point to the logic partition id
607  * @param[out]  off_set      Point to the offset in logic partition
608  * @param[in]   addr         The physical address
609  *
610  * @return 0 : On success, EIO : If an error occurred with any step
611  */
hal_flash_addr2offset(hal_partition_t * in_partition,uint32_t * off_set,uint32_t addr)612 int32_t hal_flash_addr2offset(hal_partition_t *in_partition, uint32_t *off_set, uint32_t addr)
613 {
614     FAIL_FUNCTION();
615     return 0;
616 }
617 
ota_set_bootinfo_zone_num(bootinfo_block block,bootinfo_zone zone)618 int ota_set_bootinfo_zone_num(bootinfo_block block, bootinfo_zone zone)
619 {
620     if (block >= BOOTINFO_INVALID || zone >= BOOTINFO_ZONE_MAX) {
621         return BOOTINFO_ZONE_MAX;
622     }
623 
624     if (block == BOOTINFO_ORIGIN) {
625         cur_bootinfo_zone = zone;
626     } else if (block == BOOTINFO_BACKUP) {
627         cur_bootinfoBK_zone = zone;
628     }
629 
630     return 0;
631 }
632 
ota_get_bootinfo_zone_num(bootinfo_block block)633 bootinfo_zone ota_get_bootinfo_zone_num(bootinfo_block block)
634 {
635     if (block == BOOTINFO_ORIGIN) {
636         return cur_bootinfo_zone;
637     } else if (block == BOOTINFO_BACKUP) {
638         return cur_bootinfoBK_zone;
639     } else {
640         return BOOTINFO_ZONE_MAX;
641     }
642 }
643 
ota_set_bootinfo_crc32value(MiscDataInfo * info)644 int ota_set_bootinfo_crc32value(MiscDataInfo *info)
645 {
646     uint32_t crc32_value = 0;
647     uint8_t *flash_pointer = NULL;
648 
649     flash_pointer = (uint8_t *)(info);
650     crc32_value = crc32_c(crc32_value, (uint8_t *)(flash_pointer + OTA_BOOT_INFO_HEAD_LEN), info->len);
651     info->crcVal = crc32_value;
652 
653     return ERR_OK;
654 }
655 
ota_write_bootinfo_to_flash(MiscDataInfo * info,bootinfo_block block,bootinfo_zone zone)656 int ota_write_bootinfo_to_flash(MiscDataInfo *info, bootinfo_block block, bootinfo_zone zone)
657 {
658     int ret = 0;
659     uint32_t lock = 0;
660     bootinfo_zone cur_zone = 0, next_zone = 0;
661     uint32_t cur_addr = 0;
662     uint32_t next_addr = 0;
663     uint8_t buffer[FLASH_SECTOR_SIZE_IN_BYTES] = {0};
664 
665     if (block >= BOOTINFO_INVALID) {
666         return ERR_PARAMETER;
667     }
668 
669     ota_set_bootinfo_crc32value(info);
670 
671     cur_zone = zone;
672     next_zone = (cur_zone + 1) % (BOOT_INFO_A_B_SIZE / FLASH_SECTOR_SIZE_IN_BYTES);
673     if (block == BOOTINFO_ORIGIN) {
674         cur_addr = BOOT_INFO_A_ADDR + cur_zone * FLASH_SECTOR_SIZE_IN_BYTES;
675         next_addr = BOOT_INFO_A_ADDR + next_zone * FLASH_SECTOR_SIZE_IN_BYTES;
676     } else if (block == BOOTINFO_BACKUP) {
677         cur_addr = BOOT_INFO_B_ADDR + cur_zone * FLASH_SECTOR_SIZE_IN_BYTES;
678         next_addr = BOOT_INFO_B_ADDR + next_zone * FLASH_SECTOR_SIZE_IN_BYTES;
679     }
680 
681     pmu_flash_write_config();
682     memcpy(buffer, (uint8_t *)info, sizeof(MiscDataInfo));
683 
684     //erase current sector
685     lock = int_lock_global();
686     ret = NORFLASH_API_WRAP(hal_norflash_erase)(HAL_FLASH_ID_0, cur_addr, FLASH_SECTOR_SIZE_IN_BYTES);
687     int_unlock_global(lock);
688     if (ret != HAL_NORFLASH_OK) {
689         SetFlashBadOptionInfo(HAL_PARTITION_MISC, cur_addr, FLASH_ERASE);
690         goto end;
691     }
692 
693     // erase next sector
694     lock = int_lock_global();
695     ret = NORFLASH_API_WRAP(hal_norflash_erase)(HAL_FLASH_ID_0, next_addr, FLASH_SECTOR_SIZE_IN_BYTES);
696     int_unlock_global(lock);
697     if (ret != HAL_NORFLASH_OK) {
698         SetFlashBadOptionInfo(HAL_PARTITION_MISC, next_addr, FLASH_ERASE);
699         goto end;
700     }
701 
702     // write next sector
703     lock = int_lock_global();
704     ret = NORFLASH_API_WRAP(hal_norflash_write)(HAL_FLASH_ID_0, next_addr, buffer, FLASH_SECTOR_SIZE_IN_BYTES);
705     int_unlock_global(lock);
706     if (ret != HAL_NORFLASH_OK) {
707         SetFlashBadOptionInfo(HAL_PARTITION_MISC, next_addr, FLASH_WRITE);
708         goto end;
709     }
710 
711     // update bootinfo current zone number
712     ret = ota_set_bootinfo_zone_num(block, next_zone);
713 
714 end:
715     pmu_flash_read_config();
716     return ret;
717 }
718 
ota_check_bootinfo_block(bootinfo_block block)719 int ota_check_bootinfo_block(bootinfo_block block)
720 {
721     MiscDataInfo *info = NULL;
722     uint32_t crc32_value = 0;
723     uint8_t *flash_pointer = NULL;
724 
725     if (block >= BOOTINFO_INVALID) {
726         return ERR_PARAMETER;
727     }
728 
729     for (bootinfo_zone num = BOOTINFO_ZONE_0; num < BOOTINFO_ZONE_MAX; num++) {
730         if (block == BOOTINFO_ORIGIN) {
731             info = (MiscDataInfo *)(FLASH_NC_BASE + BOOT_INFO_A_ADDR + num * FLASH_SECTOR_SIZE_IN_BYTES);
732         } else if (block == BOOTINFO_BACKUP) {
733             info = (MiscDataInfo *)(FLASH_NC_BASE + BOOT_INFO_B_ADDR + num * FLASH_SECTOR_SIZE_IN_BYTES);
734         }
735 
736         if (info->headerMagic != MISC_HEADER_MAGIC) {
737             continue;
738         }
739 
740         flash_pointer = (uint8_t *)(info);
741         crc32_value = crc32_c(crc32_value, (uint8_t *)(flash_pointer + OTA_BOOT_INFO_HEAD_LEN), info->len);
742         if (crc32_value == info->crcVal) {
743             if (block == BOOTINFO_ORIGIN) {
744                 if (ota_get_bootinfo_zone_num(BOOTINFO_ORIGIN) != num) {
745                     ota_set_bootinfo_zone_num(BOOTINFO_ORIGIN, num);
746                 }
747                 if (ota_get_bootinfo_zone_num(BOOTINFO_BACKUP) != num) {
748                     ota_set_bootinfo_zone_num(BOOTINFO_BACKUP, num);
749                 }
750             } else if (block == BOOTINFO_BACKUP) {
751                 // copy bootinfo from BACKUP zone to ORIGIN zone
752                 ota_write_bootinfo_to_flash(info, BOOTINFO_ORIGIN,
753                                             (num + BOOT_INFO_A_B_SIZE / FLASH_SECTOR_SIZE_IN_BYTES - 1) %
754                                                 (BOOT_INFO_A_B_SIZE / FLASH_SECTOR_SIZE_IN_BYTES));
755 
756                 if (ota_get_bootinfo_zone_num(BOOTINFO_ORIGIN) != num) {
757                     ota_set_bootinfo_zone_num(BOOTINFO_ORIGIN, num);
758                 }
759                 if (ota_get_bootinfo_zone_num(BOOTINFO_BACKUP) != num) {
760                     ota_set_bootinfo_zone_num(BOOTINFO_BACKUP, num);
761                 }
762             }
763             return 0;
764         }
765     }
766 
767     return ERR_PARAMETER;
768 }
769 
ota_set_bootinfo_to_zoneAB(MiscDataInfo * info)770 int ota_set_bootinfo_to_zoneAB(MiscDataInfo *info)
771 {
772     int ret = 0;
773 
774     ret = ota_write_bootinfo_to_flash(info, BOOTINFO_ORIGIN, ota_get_bootinfo_zone_num(BOOTINFO_ORIGIN));
775     if (ret) {
776     }
777 
778     ret = ota_write_bootinfo_to_flash(info, BOOTINFO_BACKUP, ota_get_bootinfo_zone_num(BOOTINFO_BACKUP));
779     if (ret) {
780     }
781 
782     return ret;
783 }
784 
ota_set_default_bootinfo_to_zoneAB(void)785 void ota_set_default_bootinfo_to_zoneAB(void)
786 {
787     MiscDataInfo info;
788     int ret = 0;
789 
790     info.headerMagic = MISC_HEADER_MAGIC;
791     info.len = OTA_BOOT_INFO_BODY_LEN;
792     info.curbootArea = BOOT_AREA_A;
793     info.upgMode = UPG_MODE_NORMAL;
794     info.quietUpgFlg = NORMAL_OTA;
795     info.timerRebootFlg = NORMAL_REBOOT;
796     info.bootTimes = 0;
797     info.rdMode.rdDataLen = 0;
798 
799     memset(&info.rdMode.rdData[0], 0, RD_DATA_LEN_MAX);
800     memset(&info.rdMode.rdSign[0], 0, RD_SIGN_LEN_MAX);
801 
802     ota_set_bootinfo_zone_num(BOOTINFO_ORIGIN, BOOTINFO_ZONE_5);
803     ota_set_bootinfo_zone_num(BOOTINFO_BACKUP, BOOTINFO_ZONE_5);
804 
805     ret = ota_set_bootinfo_to_zoneAB(&info);
806     if (ret) {
807         return;
808     }
809 }
810 
ota_get_valid_bootinfo_block(void)811 bootinfo_block ota_get_valid_bootinfo_block(void)
812 {
813     int ret = -1;
814 
815     ret = ota_check_bootinfo_block(BOOTINFO_ORIGIN);
816     if (!ret) {
817         return BOOTINFO_ORIGIN;
818     } else {
819         ret = ota_check_bootinfo_block(BOOTINFO_BACKUP);
820         if (!ret) {
821             return BOOTINFO_ORIGIN;
822         } else {
823             // first boot or both boot info bad, set both to default.
824             ota_set_default_bootinfo_to_zoneAB();
825             return BOOTINFO_ORIGIN;
826         }
827     }
828 }
829 
ota_get_bootinfo(MiscDataInfo * info,bootinfo_block block,bootinfo_zone zone)830 int ota_get_bootinfo(MiscDataInfo *info, bootinfo_block block, bootinfo_zone zone)
831 {
832     uint32_t lock = 0;
833     uint32_t start_addr = 0;
834 
835     if (block >= BOOTINFO_INVALID) {
836         return ERR_PARAMETER;
837     }
838 
839     if (zone >= BOOTINFO_ZONE_MAX) {
840         return ERR_PARAMETER;
841     }
842 
843     if (block == BOOTINFO_ORIGIN) {
844         start_addr = BOOT_INFO_A_ADDR + zone * FLASH_SECTOR_SIZE_IN_BYTES;
845     } else if (block == BOOTINFO_BACKUP) {
846         start_addr = BOOT_INFO_B_ADDR + zone * FLASH_SECTOR_SIZE_IN_BYTES;
847     }
848 
849     pmu_flash_write_config();
850     lock = int_lock_global();
851     NORFLASH_API_WRAP(hal_norflash_read)(HAL_FLASH_ID_0, start_addr, (uint8_t *)info, sizeof(MiscDataInfo));
852     int_unlock_global(lock);
853     pmu_flash_read_config();
854 
855     return ERR_OK;
856 }
857 
SetMiscData(MiscDataType type,const void * data,uint32_t dataLen)858 int SetMiscData(MiscDataType type, const void *data, uint32_t dataLen)
859 {
860     MiscDataInfo ctrl;
861     int ret = 0;
862     bootinfo_block block = BOOTINFO_INVALID;
863 
864     FlashosMutexWait();
865     block = ota_get_valid_bootinfo_block();
866 
867     ret = ota_get_bootinfo(&ctrl, block, ota_get_bootinfo_zone_num(block));
868     if (ret) {
869         osMutexRelease(FlashMutex);
870         return ret;
871     }
872 
873     switch (type) {
874     case MISC_CUR_BOOT_AREA:
875         memcpy(&ctrl.curbootArea, data, dataLen);
876         break;
877     case MISC_UPG_MODE:
878         memcpy(&ctrl.upgMode, data, dataLen);
879         break;
880     case MISC_QUIET_UPG_FLAG:
881         memcpy(&ctrl.quietUpgFlg, data, dataLen);
882         break;
883     case MISC_TIMER_REBOOT_FLAG:
884         memcpy(&ctrl.timerRebootFlg, data, dataLen);
885         break;
886     case MISC_BOOT_TIMES:
887         memcpy(&ctrl.bootTimes, data, dataLen);
888         break;
889     case MISC_RD_MODE_INFO:
890         memcpy(&ctrl.rdMode.rdDataLen, data, dataLen);
891         ctrl.len += dataLen;
892         break;
893     default:
894         return ERR_PARAMETER;
895     }
896 
897     ret = ota_set_bootinfo_to_zoneAB(&ctrl);
898     osMutexRelease(FlashMutex);
899 
900     return ret;
901 }
902 
GetMiscData(MiscDataType type,void * data,uint32_t dataLen)903 int GetMiscData(MiscDataType type, void *data, uint32_t dataLen)
904 {
905     MiscDataInfo ctrl;
906     int ret = 0;
907     bootinfo_block block = BOOTINFO_INVALID;
908 
909     if (type >= MISC_DATA_MAX) {
910         return ERR_PARAMETER;
911     }
912 
913     FlashosMutexWait();
914     block = ota_get_valid_bootinfo_block();
915     ret = ota_get_bootinfo(&ctrl, block, ota_get_bootinfo_zone_num(block));
916     if (ret) {
917         osMutexRelease(FlashMutex);
918         return ret;
919     }
920     osMutexRelease(FlashMutex);
921 
922     switch (type) {
923     case MISC_CRC_VALUE:
924         memcpy(data, &ctrl.crcVal, dataLen);
925         break;
926     case MISC_DATA_LENGTH:
927         memcpy(data, &ctrl.len, dataLen);
928         break;
929     case MISC_CUR_BOOT_AREA:
930         memcpy(data, &ctrl.curbootArea, dataLen);
931         break;
932     case MISC_UPG_MODE:
933         memcpy(data, &ctrl.upgMode, dataLen);
934         break;
935     case MISC_QUIET_UPG_FLAG:
936         memcpy(data, &ctrl.quietUpgFlg, dataLen);
937         break;
938     case MISC_TIMER_REBOOT_FLAG:
939         memcpy(data, &ctrl.timerRebootFlg, dataLen);
940         break;
941     case MISC_BOOT_TIMES:
942         memcpy(data, &ctrl.bootTimes, dataLen);
943         break;
944     case MISC_RD_MODE_INFO:
945         memcpy(data, &ctrl.rdMode.rdDataLen, dataLen);
946         break;
947     default:
948         return ERR_PARAMETER;
949     }
950 
951     return ERR_OK;
952 }
953 
ota_flash_read(const hal_partition_t partition,const uint32_t addr,uint8_t * dst,const uint32_t size)954 int ota_flash_read(const hal_partition_t partition, const uint32_t addr, uint8_t *dst, const uint32_t size)
955 {
956     int ret = 0;
957     uint32_t lock = 0;
958     hal_logic_partition_t partitionInfo;
959     uint32_t flash_offset = 0;
960 
961     if (NULL == dst) {
962         ret = -1;
963         goto RETURN;
964     }
965 
966     ret = hal_flash_info_get(partition, &partitionInfo);
967     if (ret) {
968         return ERR_RETURN;
969     }
970 
971     flash_offset = addr + partitionInfo.partition_start_addr;
972 
973     FlashosMutexWait();
974     pmu_flash_write_config();
975     lock = int_lock_global();
976     ret = NORFLASH_API_WRAP(hal_norflash_read)(HAL_FLASH_ID_0, flash_offset, dst, size);
977     int_unlock_global(lock);
978     pmu_flash_read_config();
979     osMutexRelease(FlashMutex);
980 
981 RETURN:
982     return ret;
983 }
984 
ota_feed_watchdog(void)985 static void ota_feed_watchdog(void)
986 {
987 #ifdef __WATCHER_DOG_RESET__
988     app_wdt_ping();
989 #endif
990 }
991 
ota_partition_common_erase_write(const hal_partition_t partition,uint32_t start_addr,uint32_t erase_len,uint8_t * src_buf,uint32_t src_len)992 static int ota_partition_common_erase_write(const hal_partition_t partition, uint32_t start_addr, uint32_t erase_len, uint8_t *src_buf, uint32_t src_len)
993 {
994     int ret = 0;
995     uint32_t lock = 0;
996 
997     lock = int_lock_global();
998 
999     ret = NORFLASH_API_WRAP(hal_norflash_erase)(HAL_FLASH_ID_0, start_addr, erase_len);
1000     if (ret != HAL_NORFLASH_OK) {
1001         SetFlashBadOptionInfo(partition, start_addr, FLASH_ERASE);
1002         int_unlock_global(lock);
1003         return ERR_RETURN;
1004     }
1005 
1006     ret = NORFLASH_API_WRAP(hal_norflash_write)(HAL_FLASH_ID_0, start_addr, src_buf, src_len);
1007     if (ret != HAL_NORFLASH_OK) {
1008         SetFlashBadOptionInfo(partition, start_addr, FLASH_WRITE);
1009         int_unlock_global(lock);
1010         ret = ERR_RETURN;
1011     }
1012 
1013     int_unlock_global(lock);
1014 
1015     return ret;
1016 }
1017 
ota_partition_erase_write(const hal_partition_t partition,uint32_t * start_addr,uint8_t * src_buf,uint32_t src_len)1018 static int ota_partition_erase_write(const hal_partition_t partition, uint32_t *start_addr, uint8_t *src_buf, uint32_t src_len)
1019 {
1020     int ret = 0;
1021     uint32_t lock = 0, num = 0;
1022 
1023     lock = int_lock_global();
1024 
1025     for (num = 0; num < src_len / OTA_MALLOC_BUF_SIZE; num++) {
1026         ret = NORFLASH_API_WRAP(hal_norflash_erase)(HAL_FLASH_ID_0, *start_addr, OTA_MALLOC_BUF_SIZE);
1027         if (ret != HAL_NORFLASH_OK) {
1028             SetFlashBadOptionInfo(partition, *start_addr, FLASH_ERASE);
1029             int_unlock_global(lock);
1030             return ERR_RETURN;
1031         }
1032 
1033         ret = NORFLASH_API_WRAP(hal_norflash_write)(HAL_FLASH_ID_0, *start_addr, src_buf, OTA_MALLOC_BUF_SIZE);
1034         if (ret != HAL_NORFLASH_OK) {
1035             SetFlashBadOptionInfo(partition, *start_addr, FLASH_WRITE);
1036             int_unlock_global(lock);
1037             ret = ERR_RETURN;
1038         }
1039 
1040         *start_addr += OTA_MALLOC_BUF_SIZE;
1041         src_buf += OTA_MALLOC_BUF_SIZE;
1042     }
1043 
1044     int_unlock_global(lock);
1045 
1046     return ret;
1047 }
1048 
ota_partition_read_erase_write(const hal_partition_t partition,uint32_t start_addr,uint8_t * dst_buf,uint32_t dst_buf_len,uint32_t dst_offset,uint8_t * src_buf,uint32_t src_len)1049 static int ota_partition_read_erase_write(const hal_partition_t partition, uint32_t start_addr, uint8_t *dst_buf, uint32_t dst_buf_len, uint32_t dst_offset, uint8_t *src_buf, uint32_t src_len)
1050 {
1051     int ret = 0;
1052     uint32_t lock;
1053 
1054     lock = int_lock_global();
1055     ret = NORFLASH_API_WRAP(hal_norflash_read)(HAL_FLASH_ID_0, start_addr, dst_buf, dst_buf_len);
1056     int_unlock_global(lock);
1057     if (ret != HAL_NORFLASH_OK) {
1058         SetFlashBadOptionInfo(partition, start_addr, FLASH_READ);
1059         return ret;
1060     }
1061 
1062     memcpy((dst_buf + dst_offset), src_buf, src_len);
1063 
1064     ret = ota_partition_common_erase_write(partition, start_addr, dst_buf_len, dst_buf, dst_buf_len);
1065     return ret;
1066 }
1067 
ota_partition_check_magic(const hal_partition_t partition,const uint32_t addr)1068 static int ota_partition_check_magic(const hal_partition_t partition, const uint32_t addr)
1069 {
1070     int ret;
1071     uint32_t num;
1072     hal_logic_partition_t partition_info;
1073     uint8_t ota_partition[6] = {HAL_PARTITION_BOOT2A, HAL_PARTITION_BOOT2B, HAL_PARTITION_TRUSTZONEA,
1074                                 HAL_PARTITION_TRUSTZONEB, HAL_PARTITION_CM33_MAIN, HAL_PARTITION_SYSTEM_MINI};
1075     uint8_t read_buf[FLASH_SECTOR_SIZE_IN_BYTES] = {0};
1076     uint8_t magic_buf[4] = {0};
1077 
1078     ret = hal_flash_info_get(partition, &partition_info);
1079     if (ret) {
1080         return ERR_RETURN;
1081     }
1082 
1083     for (num = 0; num < sizeof(ota_partition); num++) {
1084         if ((partition == ota_partition[num]) && (addr == 0)) {
1085             uint32_t flash_offset = partition_info.partition_start_addr;
1086             magic_buf[0] = 0x1c;
1087             magic_buf[1] = 0xec;
1088             magic_buf[2] = 0x57;
1089             magic_buf[3] = 0xbe;
1090 
1091             ret = ota_partition_read_erase_write(partition, flash_offset, read_buf, sizeof(read_buf), 0, magic_buf, sizeof(magic_buf));
1092             if (ret != HAL_NORFLASH_OK) {
1093                 return ERR_RETURN;
1094             }
1095             break;
1096         }
1097     }
1098 
1099     return ret;
1100 }
1101 
ota_flash_write(const hal_partition_t partition,const uint32_t addr,const uint8_t * src,const uint32_t size)1102 int ota_flash_write(const hal_partition_t partition, const uint32_t addr, const uint8_t *src, const uint32_t size)
1103 {
1104     int ret = -1;
1105     uint32_t left_len = 0, align_len = 0, fill_len = 0, flash_offset = 0, lengthToBurn = size;
1106     uint8_t *ptrSource = (uint8_t *)src;
1107     uint8_t *buf = NULL;
1108     hal_logic_partition_t partitionInfo;
1109 
1110     if (NULL == ptrSource)
1111         return ERR_RETURN;
1112 
1113     hal_flash_info_get(partition, &partitionInfo);
1114     flash_offset = addr + partitionInfo.partition_start_addr;
1115 
1116     if ((addr % OTA_MALLOC_BUF_SIZE != 0) || (lengthToBurn % OTA_MALLOC_BUF_SIZE != 0)) {
1117         buf = (uint8_t *)malloc(OTA_MALLOC_BUF_SIZE);
1118         if (!buf)
1119             return ERR_RETURN;
1120     }
1121 
1122     ota_feed_watchdog();
1123 
1124     FlashosMutexWait();
1125     pmu_flash_write_config();
1126 
1127     if (flash_offset % OTA_MALLOC_BUF_SIZE != 0) {
1128         left_len = OTA_MALLOC_BUF_SIZE - flash_offset % OTA_MALLOC_BUF_SIZE;
1129         fill_len = (left_len >= lengthToBurn) ? lengthToBurn : left_len;
1130         align_len = flash_offset - flash_offset % OTA_MALLOC_BUF_SIZE;
1131         ret = ota_partition_read_erase_write(partition, align_len, buf, OTA_MALLOC_BUF_SIZE, (flash_offset % OTA_MALLOC_BUF_SIZE), ptrSource, fill_len);
1132         if (ret != HAL_NORFLASH_OK)
1133             goto end;
1134         lengthToBurn -= fill_len;
1135         flash_offset += fill_len;
1136     }
1137 
1138     if (lengthToBurn > 0) {
1139         ret = ota_partition_erase_write(partition, &flash_offset, ptrSource, lengthToBurn);
1140         if (ret != HAL_NORFLASH_OK)
1141             goto end;
1142 
1143         if (lengthToBurn % OTA_MALLOC_BUF_SIZE) {
1144             ret = ota_partition_read_erase_write(partition, flash_offset, buf, OTA_MALLOC_BUF_SIZE, 0, ptrSource, (lengthToBurn % OTA_MALLOC_BUF_SIZE));
1145             if (ret != HAL_NORFLASH_OK)
1146                 goto end;
1147         }
1148     }
1149 
1150     ota_partition_check_magic(partition, addr);
1151 
1152 end:
1153     pmu_flash_read_config();
1154     if ((addr % OTA_MALLOC_BUF_SIZE != 0) || (lengthToBurn % OTA_MALLOC_BUF_SIZE != 0))
1155         free(buf);
1156 
1157     hal_cache_invalidate_all(HAL_CACHE_ID_I_CACHE);
1158     osMutexRelease(FlashMutex);
1159 
1160     return ret;
1161 }
1162 
1163 /*
1164  * 获取当前是那个区间:partition
1165  * 获取具体那个坏块号
1166  */
GetFlashBadBlockNum(hal_partition_t partition,uint32_t * blockNum)1167 int32_t GetFlashBadBlockNum(hal_partition_t partition, uint32_t *blockNum)
1168 {
1169     struct HAL_FLASH_BAD_INFO *flashbadinfo = NULL;
1170     if (blockNum == NULL) {
1171         return -1;
1172     }
1173 
1174     for (size_t i = 0; i < BLOCK_MAX_INFO; i++) {
1175         flashbadinfo = &g_flashBadInfo[i];
1176         if (flashbadinfo->partition == partition) {
1177             *blockNum = flashbadinfo->blocknum;
1178             break;
1179         }
1180     }
1181 
1182     return 0;
1183 }
1184 
1185 /*
1186  * 获取当前是那个区间:partition
1187  * 获取区间上偏移(算出具体物理地址):offset
1188  * 获取具体那个坏块号:
1189  */
GetFlashBadBlock(hal_partition_t * partition,uint32_t * offset,uint32_t * blockNum)1190 int32_t GetFlashBadBlock(hal_partition_t *partition, uint32_t *offset, uint32_t *blockNum)
1191 {
1192     struct HAL_FLASH_BAD_INFO *flashbadinfo = NULL;
1193     if (partition == NULL || offset == NULL || blockNum == NULL) {
1194         return -1;
1195     }
1196 
1197     flashbadinfo = GetFlashBadOptionInfo();
1198     *partition = flashbadinfo->partition;
1199     *offset = flashbadinfo->offset;
1200     *blockNum = flashbadinfo->blocknum;
1201 
1202     return 0;
1203 }
1204 
1205 /*
1206  * 获取集成Flash芯片的厂家ID:factoryID
1207  * 获取集成Flash芯片的设备ID:deviceID
1208  */
GetFlashType(int32_t * factoryID,int32_t * deviceID)1209 int32_t GetFlashType(int32_t *factoryID, int32_t *deviceID)
1210 {
1211     uint8_t flash_id[HAL_NORFLASH_DEVICE_ID_LEN];
1212     int32_t a, b;
1213 
1214     NORFLASH_API_WRAP(hal_norflash_get_id)(HAL_FLASH_ID_0, flash_id, ARRAY_SIZE(flash_id));
1215 
1216     TRACE(3, "FLASH_ID: %02X-%02X-%02X", flash_id[0], flash_id[1], flash_id[2]);
1217     *factoryID = flash_id[0];
1218 
1219     a = 0xffff00ff | (flash_id[1] << 8);
1220     b = 0xffffff00 | flash_id[2];
1221 
1222     *deviceID = a & b;
1223 
1224     return 0;
1225 }
1226 
1227 /*
1228  * 当前是区间:partition
1229  * 当前是块号:blockNum
1230  * 读或者写:op
1231  * 获取该块号的写或者擦的次数:times
1232  */
GetFlashRewriteCycle(hal_partition_t partition,uint32_t blockNum,uint32_t op,uint32_t * times)1233 int32_t GetFlashRewriteCycle(hal_partition_t partition, uint32_t blockNum, uint32_t op, uint32_t *times)
1234 {
1235     struct HAL_FLASH_RW_INFO *FlashRwInfo = NULL;
1236 
1237     if (times == NULL || op >= MAX_FLASH_OPTIONS) {
1238         return -1;
1239     }
1240 
1241     for (size_t i = 0; i < RW_MAX_PARTITION; i++) {
1242         FlashRwInfo = &g_flashRwInfo[i];
1243         if (FlashRwInfo->partition == partition) {
1244             for (size_t j = 0; j < RW_MAX_BLOCK; j++) {
1245                 if (FlashRwInfo->blockInfo[j].blocknum == blockNum) {
1246                     *times = FlashRwInfo->blockInfo[j].count[op];
1247                     break;
1248                 }
1249             }
1250         }
1251     }
1252 
1253     return 0;
1254 }
1255 
GetFlashRewriteCycleCount(hal_partition_t partition,uint32_t op,uint32_t * count)1256 int32_t GetFlashRewriteCycleCount(hal_partition_t partition, uint32_t op, uint32_t *count)
1257 {
1258     uint32_t tempTimes = 0;
1259     uint32_t countTimes = 0;
1260     uint32_t partitionStartBlockNum;
1261     uint32_t partitionEndBlockNum;
1262     hal_logic_partition_t info;
1263 
1264     if (count == NULL) {
1265         TRACE(0, "count is NULL\r\n");
1266         return -1;
1267     }
1268 
1269     if (hal_flash_info_get(partition, &info) != 0) {
1270         TRACE(0, "hal_flash_info_get fail\r\n");
1271         return -1;
1272     }
1273 
1274     partitionStartBlockNum = info.partition_start_addr / ONE_BLOCK_SIZE;
1275     partitionEndBlockNum = (info.partition_start_addr + info.partition_length) / ONE_BLOCK_SIZE;
1276 
1277     for (size_t blockNum = partitionStartBlockNum; blockNum < partitionEndBlockNum; blockNum++) {
1278         GetFlashRewriteCycle(partition, blockNum, op, &tempTimes);
1279         countTimes += tempTimes;
1280     }
1281 
1282     *count = countTimes;
1283 
1284     return 0;
1285 }
1286 
1287 /*
1288  * 当前是区间:partition
1289  * 当前是块号:blockNum
1290  * 读或者写:op
1291  * 获取该块号的写或者擦的次数:blockTimes
1292  */
GetFlashStatisticInfo(hal_partition_t partition,uint32_t blockNum,uint32_t op,uint32_t * blockTimes)1293 int32_t GetFlashStatisticInfo(hal_partition_t partition, uint32_t blockNum, uint32_t op, uint32_t *blockTimes)
1294 {
1295     struct HAL_FLASH_BAD_INFO *flashBadInfo = NULL;
1296     uint32_t blockcount = 0;
1297 
1298     if (blockTimes == NULL) {
1299         TRACE(0, "blockTimes is NULL\r\n");
1300         return -1;
1301     }
1302 
1303     for (size_t i = 0; i < BLOCK_MAX_INFO; i++) {
1304         flashBadInfo = &g_flashBadInfo[i];
1305         if ((flashBadInfo->partition == partition) && (flashBadInfo->blocknum <= blockNum) && (flashBadInfo->partition == op)) {
1306             blockcount++;
1307         }
1308     }
1309 
1310     *blockTimes = blockcount;
1311 
1312     return 0;
1313 }
1314