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