ssd202d-badblock-坏块检测
这边文章讲述的是坏快检测功能
思路:
1.第一次烧录固件会实现跳坏块,但是后续使用会导致坏块的产生;
于是我在uboot环境变量添加了两个变量来控制坏快
lb_badnum = //坏块个数
lb_badoff = //坏块所在位置
![]()
2.第一次开机会根据lb_badnum是否存在判断,如果不存在则保存上面坏块信息,跳过坏块功能
3.第二次开机之后会获取环境变量lb_badnum和lb_badoff;
3.1.然后检测实际坏块数,进行对比,如果有新增坏块, 则判断新坏块产生的所在分区;
3.2.然后判断所在分区坏块大小加上固件大小后是否超出划分的分区空间;
3.3.执行对应的分区还原;

commit 0ae66e0a3d1366aa90b4661b86203345f4ae02bd (HEAD -> master)
Author: longmin <1938049502@qq.com>
Date: Tue Dec 10 16:44:44 2024 +0800add cmd_lbbad.c support bad block detection functiondiff --git a/boot/common/Kconfig b/boot/common/Kconfig
index 516a279af..11cb2c30a 100755
--- a/boot/common/Kconfig
+++ b/boot/common/Kconfig
@@ -365,4 +365,10 @@ config XZconfig MZbool "MZ"config SILENT_CONSOLE
- bool "SILENT_CONSOLE"
\ No newline at end of file
+ bool "SILENT_CONSOLE"
+
+config CMD_LBBAD
+ bool "LBBAD"
+ help
+ This enables the command CONFIG_CMD_LBBAD power on detection of bad
+ blocks.
\ No newline at end of file
diff --git a/boot/common/Makefile b/boot/common/Makefile
index 85ba0bffd..0d54285f5 100755
--- a/boot/common/Makefile
+++ b/boot/common/Makefile
@@ -344,4 +344,5 @@ endifobj-$(CONFIG_CMD_LBCHK) += cmd_lbchk.oobj-$(CONFIG_CMD_LBFDT) += cmd_lbfdt.o
+obj-$(CONFIG_CMD_LBBAD) += cmd_lbbad.oobj-y += cmd_sar.o
diff --git a/boot/common/autoboot.c b/boot/common/autoboot.c
index 60f7b2291..927dcd18a 100755
--- a/boot/common/autoboot.c
+++ b/boot/common/autoboot.c
@@ -585,6 +585,10 @@ void autoboot_command(const char *s)boot:debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
+#if defined (CONFIG_CMD_LBBAD)
+ extern int run_lbbadblock(void);
+ run_lbbadblock(); /* bad block inspection */
+#endif#if defined (CONFIG_CMD_LBCHK) && defined (LONBON_CHECK_RUNCMD)extern int run_lbcheck(int cmd);run_lbcheck(LONBON_CHECK_RUNCMD);
diff --git a/boot/common/cmd_lbbad.c b/boot/common/cmd_lbbad.c
new file mode 100755
index 000000000..5bfa4890c
--- /dev/null
+++ b/boot/common/cmd_lbbad.c
@@ -0,0 +1,503 @@
+#include <common.h>^M
+#include <command.h>^M
+#include <malloc.h>^M
+#include <nand.h>^M
+#include <u-boot/md5.h>^M
+#include <asm/io.h>^M
+#include <spi.h>^M
+#include <spi_flash.h>^M
+#if (1 == CONFIG_LONBON_LED) || (1 == LONBON_CMD_CHECK_2BTN_FOR_RESTORE)^M
+#include "../drivers/mstar/gpio/infinity2m/gpio.h"^M
+#include "../drivers/mstar/gpio/drvGPIO.h"^M
+#endif^M
+^M
+//#define LB_DEBUG^M
+^M
+#ifdef LB_DEBUG^M
+#define LBCHK_DEBUG(msg...) printf(msg)^M
+#else^M
+#define LBCHK_DEBUG(msg...) do{}while(0)^M
+#endif^M
+^M
+typedef int BOOL;^M
+^M
+#ifndef FALSE^M
+#define FALSE 0^M
+#endif^M
+^M
+#ifndef TRUE^M
+#define TRUE 1^M
+#endif^M
+^M
+#ifdef CONFIG_YAFFS2^M
+extern void cmd_yaffs_devconfig(char *mp, int flash_dev, int start_block, int end_block);^M
+extern void cmd_yaffs_mount(char *mp);^M
+extern void cmd_yaffs_umount(char *mp);^M
+extern void cmd_yaffs_mread_file(char *fn, char *addr);^M
+#endif^M
+^M
+#define BADBLOCK_MAX 200^M
+^M
+extern int lb_nand_get_badblock_number(ulong *badblock_list);^M
+extern int lbcmd_get_imagename_by_cmd(char* imgname, unsigned char cmd);^M
+extern int lonbon_get_partitions(const char *part_name, uint *part_offset, uint *part_size);^M
+extern int lonbon_get_partitions_name(uint *off, char *part_name, uint *part_offset, uint *part_size);^M
+extern int lb_nand_flash_partition_baseAddr(const char *part_name, uint *part_offset, uint *part_size);^M
+^M
+typedef struct {^M
+ int uboot;^M
+ int kernel;^M
+ int rootfs;^M
+ int backup;^M
+ int ro;^M
+ int rw;^M
+ int ipl;^M
+ int ipl_cust;^M
+ int logo;^M
+ int factory;^M
+ int lbcmd;^M
+ int lbflash;^M
+ int lbcfg;^M
+ int env;^M
+ int key_cust;^M
+} lb_bad_partition_t;^M
+^M
+int lonbon_set_badnum(int number)^M
+{^M
+ unsigned char badnum[2];^M
+ if(number >= 0) {^M
+ memset(badnum,0,2);^M
+ badnum[0] = number + 0x30;^M
+ setenv("lb_badnum", (const char *)badnum);^M
+ run_command("saveenv", 0);^M
+ return 0;^M
+ }^M
+ return -1;^M
+}^M
+^M
+int lonbon_get_badnum(void)^M
+{^M
+ char * lb_badnum = getenv("lb_badnum");^M
+ unsigned char badnum[2];^M
+^M
+ if(lb_badnum) {^M
+ badnum[0] = *lb_badnum - 0x30;^M
+ printf("old bad_block number= %d\n",badnum[0]);^M
+ return badnum[0];^M
+ }else{^M
+ printf("%s lb_badnum=null\n", __func__);^M
+ return -1;^M
+ }^M
+ return 0;^M
+}^M
+^M
+int lonbon_number_exist(int all_number, ulong *badblock_list, ulong number){^M
+ int i;^M
+ for(i=0; i < all_number; i++)^M
+ {^M
+ if(*(badblock_list+i) == number)^M
+ {^M
+ return i;^M
+ }^M
+ }^M
+ return -1;^M
+}^M
+^M
+int lonbon_new_badblock(int all_number, ulong *badblock_list, int env_number, ulong *old_badblock_list,ulong *add_badblock_list)^M
+{^M
+ int i, j, k = 0;^M
+ bool flag;^M
+ for (i=0; i < all_number; i++){^M
+ flag = false;^M
+ for (j=0; j < all_number; j++){^M
+ if( badblock_list[i] == old_badblock_list[j] )^M
+ flag = true;^M
+ }^M
+^M
+ if(flag == false){^M
+ *(add_badblock_list + k) = badblock_list[i];^M
+ k++;^M
+ }^M
+^M
+ }^M
+^M
+ return 0;^M
+}^M
+^M
+^M
+int lonbon_get_bad_offset(int all_number, ulong *badblock_list, int number)^M
+{^M
+ int i;^M
+ char *lb_badoff = getenv("lb_badoff");^M
+ char badb_offset[1024]= {0};^M
+ ulong old_badb_list[all_number];^M
+ ulong *old_badblock_list = &old_badb_list[0];^M
+ ulong add_badb_list[all_number];^M
+ ulong *add_badblock_list = &add_badb_list[0];^M
+ char *lb_bad_off;^M
+ ulong num;^M
+^M
+ if(all_number == 0){^M
+ printf("%s not badblock_list\n", __func__);^M
+ return 0;^M
+ }^M
+^M
+ if(lb_badoff){^M
+ strcpy(badb_offset,lb_badoff);^M
+ lb_bad_off = strtok(badb_offset, "-");^M
+ num = simple_strtol(lb_bad_off, NULL, 16);^M
+ old_badb_list[0] = num;^M
+ for(i=1; i < all_number;i++ ){^M
+ lb_bad_off = strtok(NULL ,"-");^M
+ num = simple_strtol(lb_bad_off, NULL, 16);^M
+ old_badb_list[i] = num;^M
+ }^M
+ }^M
+ /* determine the partition location of the new bad block */^M
+ lonbon_new_badblock(all_number, badblock_list, number, old_badblock_list, add_badblock_list);^M
+ for(i=0; i < all_number; i++){^M
+ *(badblock_list + i) = 0;^M
+ }^M
+ for(i=0; i<number;i++){^M
+ *(badblock_list + i) = add_badb_list[i];^M
+ }^M
+^M
+ return 1;^M
+}^M
+^M
+int lonbon_set_bad_offset(int number, ulong *badblock_list)^M
+{^M
+ int i;^M
+ char commandline[10] = {0};^M
+ char badb_addr[1024]= {'0'};^M
+ if(number >= 0) {^M
+ if(number > 0) {^M
+ for(i=0;i<number;i++){^M
+ sprintf(commandline,"%08lx-", *(badblock_list+i));^M
+ strcat(badb_addr,commandline);^M
+ }^M
+ }^M
+ printf("lonbon_set_bad_offset badblock_list:%s\n",badb_addr);^M
+ setenv("lb_badoff", (const char *)badb_addr);^M
+ run_command("saveenv", 0);^M
+ return number;^M
+ }^M
+ return 0;^M
+}^M
+^M
+int lonbon_set_partitions(lb_bad_partition_t *lb_part, char *part_name)^M
+{^M
+ //printf("%s %s \n",__func__,part_name);^M
+ if(strcmp(part_name, "UBOOT0") == 0||strcmp(part_name, "UBOOT1") == 0){^M
+ lb_part->uboot += 1;^M
+ }else if(strcmp(part_name, "rootfs") == 0){^M
+ lb_part->rootfs += 1;^M
+ }else if(strcmp(part_name, "KERNEL") == 0||strcmp(part_name, "RECOVERY") == 0){^M
+ lb_part->kernel += 1;^M
+ }else if(strcmp(part_name, "backup") == 0){^M
+ lb_part->backup += 1;^M
+ }else if(strcmp(part_name, "ro") == 0){^M
+ lb_part->ro += 1;^M
+ }else if(strcmp(part_name, "rw") == 0){^M
+ lb_part->rw += 1;^M
+ }else if(strcmp(part_name, "IPL0") == 0||strcmp(part_name, "IPL1") == 0){^M
+ lb_part->ipl += 1;^M
+ }else if(strcmp(part_name, "IPL_CUST0") == 0||strcmp(part_name, "IPL_CUST1") == 0){^M
+ lb_part->ipl_cust += 1;^M
+ }else if(strcmp(part_name, "LOGO") == 0){^M
+ lb_part->logo += 1;^M
+ }else if(strcmp(part_name, "factory") == 0){^M
+ lb_part->factory += 1;^M
+ }else if(strcmp(part_name, "lbcmd") == 0){^M
+ lb_part->lbcmd += 1;;^M
+ }else if(strcmp(part_name, "lbflash") == 0||strcmp(part_name, "lbflash2") == 0){^M
+ lb_part->lbflash += 1;^M
+ }else if(strcmp(part_name, "lbcfg") == 0||strcmp(part_name, "lbcfg2") == 0){^M
+ lb_part->lbcfg += 1;^M
+ }else if(strcmp(part_name, "ENV") == 0||strcmp(part_name, "ENV1") == 0){^M
+ lb_part->env += 1;^M
+ }else if(strcmp(part_name, "KEY_CUST") == 0){^M
+ lb_part->key_cust += 1;^M
+ }else{^M
+ return -1;^M
+ }^M
+^M
+ return 0;^M
+}^M
+^M
+void lonbon_printf_bad(int num){^M
+^M
+ switch (num)^M
+ {^M
+ case 0: printf("\n");^M
+ printf("##############################################################################\n");^M
+ printf("##############################################################################\n");^M
+ printf("############################ bad block list:##################################\n");^M
+ break;^M
+ case 1: printf("\nstart all bad block list:\n");^M
+ break;^M
+ case 2: printf("\n");^M
+ printf("add bad block:\n");^M
+ printf("\n");^M
+ break;^M
+ case 3: printf("\n");^M
+ printf("##############################################################################\n");^M
+ printf("##############################################################################\n");^M
+ printf("\n");^M
+ break;^M
+ }^M
+^M
+}^M
+^M
+uint lonbon_get_pattition_firmware_size(char *fileName){^M
+ char *mntpoint = "/factory";^M
+ uint part_offset;^M
+ uint part_size;^M
+ int start_block;^M
+ int end_block;^M
+^M
+ char filename[100] = {0};^M
+ unsigned long addr= 0x21000000;^M
+ lb_nand_flash_partition_baseAddr("factory", &part_offset, &part_size);^M
+ if(!part_offset || !part_size) {^M
+ printf("#ERROR: No factory partition is found\n");^M
+ return -1;^M
+ }^M
+^M
+ start_block = part_offset/(128*1024); /* Nand flash block size is 128 KB */^M
+ end_block = (part_offset+part_size)/(128*1024)-1;^M
+^M
+ cmd_yaffs_devconfig(mntpoint,0,start_block,end_block);^M
+ cmd_yaffs_mount(mntpoint);^M
+ sprintf(filename, "%s/%s", mntpoint, fileName);^M
+ cmd_yaffs_mread_file(filename, (char *)addr);^M
+ char *str_env = getenv("filesize");^M
+ ulong filesize = simple_strtoul(str_env, NULL, 16);^M
+ size_t blocksize = nand_info[0].erasesize;^M
+ ulong wsize=(filesize/blocksize+1)*blocksize;^M
+ cmd_yaffs_umount(mntpoint);^M
+ printf("longbon filename=%s str_env=%s filesize=%lx wsize=%lx \n",filename,str_env,filesize,wsize);^M
+ return wsize;^M
+^M
+}^M
+^M
+int lonbon_pattition_firmware_size(unsigned char cmd, char *part_name, int bad_number)^M
+{^M
+ char firmware_name[32] = {0};^M
+ char *firmware_part_name = &firmware_name[0];^M
+ uint part_offset, part_size;^M
+ ulong firmware_size, firmware_size_bad;^M
+ size_t blocksize = nand_info[0].erasesize;^M
+^M
+ /* get firmware name */^M
+ lbcmd_get_imagename_by_cmd(firmware_part_name, cmd);^M
+ /* get firmware size */^M
+ firmware_size = lonbon_get_pattition_firmware_size(firmware_part_name);^M
+ /* the size after adding the bad block */^M
+ firmware_size_bad = firmware_size +( blocksize * bad_number);^M
+ /* get partitions total size */^M
+ lonbon_get_partitions(part_name, &part_offset, &part_size);^M
+^M
+ /* partitions total size > firmware size add bad block size */^M
+ if( part_size > firmware_size_bad)^M
+ {^M
+ printf("\nlonbon %s is OK! part_size=%x firmware_size_bad=%lx \n",__func__,part_size,firmware_size_bad);^M
+ return 1;^M
+ }^M
+ else {^M
+ printf("\nlonbon %s error!! part_size=%x firmware_size_bad=%lx \n",__func__,part_size,firmware_size_bad);^M
+ return -1;^M
+ }^M
+ return 0;^M
+}^M
+^M
+void lonbon_printf_bad_block(lb_bad_partition_t *lb_bad_partition, int number, ulong *bad_list, int new_number, ulong *new_bad_list){^M
+^M
+ int i, ret, flags = 0;^M
+ char write[20] = {' '};^M
+ char *write_t = &write[0];^M
+ char part_name[10] = {'0'};^M
+ char *part_name_t = &part_name[0];^M
+ ulong *badblock_list = bad_list;^M
+ char commandline[30] = {0};^M
+ uint lbflash_offset = 0,lbflash_size = 0;^M
+^M
+ if(new_number > 0){^M
+ lonbon_printf_bad(1);^M
+ }^M
+ for(i=0; i< number; i++){^M
+ memset(part_name,0,sizeof(part_name));^M
+ lonbon_get_partitions_name((uint *) *(badblock_list+i), part_name_t, &lbflash_offset, &lbflash_size);^M
+ printf("bad[%d]=0x%08lx name=%s off=0x%08x size=0x%08x end=0x%08x \n",^M
+ i, *(badblock_list+i), part_name_t, lbflash_offset, lbflash_size ,(lbflash_offset +lbflash_size -1) );^M
+ }^M
+ if(new_number > 0){^M
+ lonbon_printf_bad(2);^M
+ for(i=0; i< new_number; i++){^M
+ printf(" 0x%08lx \n", *(new_bad_list + i));^M
+ }^M
+ }^M
+ if(lb_bad_partition->factory > 0){^M
+ printf("\n warn factory partition are bad blocks !!!\n\n");^M
+ }^M
+ if(lb_bad_partition->uboot > 0){^M
+ printf("\n warn uboot partition are bad blocks !!!\n\n");^M
+ ret = lonbon_pattition_firmware_size(1,"uboot",lb_bad_partition->uboot);^M
+ if(ret > 0){^M
+ strcat(write,"1 ");^M
+ flags++;^M
+ }else{^M
+ printf("\n%s error!!!uboot insufficient partition space !!!\n",__func__ );^M
+ }^M
+ }^M
+ if(lb_bad_partition->kernel > 0){^M
+ printf("\n warn kernel partition are bad blocks !!!\n\n");^M
+ ret = lonbon_pattition_firmware_size(2,"kernel",lb_bad_partition->kernel);^M
+ if(ret > 0){^M
+ strcat(write,"2 ");^M
+ flags++;^M
+ }else{^M
+ printf("\n%s error!!!kernel insufficient partition space !!!\n",__func__ );^M
+ }^M
+ }^M
+ if(lb_bad_partition->rootfs > 0){^M
+ printf("\n warn rootfs partition are bad blocks !!!\n\n");^M
+ ret = lonbon_pattition_firmware_size(3,"rootfs",lb_bad_partition->rootfs);^M
+ if(ret > 0){^M
+ strcat(write,"3 ");^M
+ flags++;^M
+ }else{^M
+ printf("\n%s error!!!rootfs insufficient partition space !!!\n",__func__ );^M
+ }^M
+ }^M
+ if(lb_bad_partition->backup > 0){^M
+ printf("\n warn backup partition are bad blocks !!!\n\n");^M
+ }^M
+ if(lb_bad_partition->ro > 0){^M
+ printf("\n warn ro partition are bad blocks !!!\n\n");^M
+ }^M
+ if(lb_bad_partition->rw > 0){^M
+ printf("\n warn rw partition are bad blocks !!!\n\n");^M
+ }^M
+ if(lb_bad_partition->ipl > 0){^M
+ printf("\n warn ipl partition are bad blocks !!!\n\n");^M
+ ret = lonbon_pattition_firmware_size(6,"ipl",lb_bad_partition->ipl);^M
+ if(ret > 0){^M
+ strcat(write,"6 ");^M
+ flags++;^M
+ }else{^M
+ printf("\n%s error!!!ipl insufficient partition space !!!\n",__func__ );^M
+ }^M
+ }^M
+ if(lb_bad_partition->ipl_cust > 0){^M
+ printf("\n warn ipl_cust partition are bad blocks !!!\n\n");^M
+ ret = lonbon_pattition_firmware_size(7,"ipl",lb_bad_partition->ipl_cust);^M
+ if(ret > 0){^M
+ strcat(write,"7 ");^M
+ flags++;^M
+ }else{^M
+ printf("\n%s error!!!ipl_cust insufficient partition space !!!\n",__func__ );^M
+ }^M
+ }^M
+ if(lb_bad_partition->logo > 0){^M
+ printf("\n warn logo partition are bad blocks !!!\n\n");^M
+ ret = lonbon_pattition_firmware_size(8,"logo",lb_bad_partition->logo);^M
+ if(ret > 0){^M
+ //run_command("lbupgrade write 8", 0);^M
+ strcat(write,"8 ");^M
+ flags++;^M
+ }else{^M
+ printf("\n%s error!!!logo insufficient partition space !!!\n",__func__ );^M
+ }^M
+ }^M
+^M
+ if (flags > 0){^M
+ sprintf(commandline,"lbupgrade write %s", write_t);^M
+ printf("\nlonbon %s run_command: %s !!!\n", __func__ , commandline);^M
+ run_command(commandline, 0);^M
+ }^M
+^M
+ lonbon_printf_bad(3);^M
+^M
+}^M
+^M
+/* bad block inspection */^M
+int run_lbbadblock(void) ^M
+{^M
+ lb_bad_partition_t lb_bad_partition ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};^M
+ lb_bad_partition_t *lb_bad_partition_r = &lb_bad_partition;^M
+ int ret, i;^M
+ char part_name[10] = {'0'};^M
+ char *part_name_t = &part_name[0];^M
+ uint lbflash_offset = 0,lbflash_size = 0;^M
+ ulong badblock_list[BADBLOCK_MAX];^M
+ ulong *list_badblock = &badblock_list[0];^M
+ int badblock_number , lb_badnum;^M
+ bool new_badblock = false;^M
+^M
+ lonbon_printf_bad(0);^M
+ memset(badblock_list,0,sizeof(badblock_list));^M
+ badblock_number = lb_nand_get_badblock_number(list_badblock);^M
+ ulong bad_list[badblock_number];^M
+ ulong *bad_list_t = &bad_list[0];^M
+^M
+ for( i = 0; i < badblock_number; i++){^M
+ bad_list[i] = badblock_list[i];^M
+ }^M
+^M
+ if(badblock_number < 0){^M
+ printf("error! get badblock number failed! :%d\n",badblock_number);^M
+ return badblock_number;^M
+ }else{^M
+ printf("bad badblock number: %d\n",badblock_number);^M
+ }^M
+^M
+ lb_badnum = lonbon_get_badnum();/* get lb_badnum */^M
+ if(lb_badnum < 0){ /* the first burning is not processed */^M
+^M
+ ret = lonbon_set_badnum(badblock_number);/* directly save the number of burned blocks */^M
+ if(ret < 0){^M
+ printf("error %s badblock_number=null\n",__func__);^M
+ }^M
+ printf("lonbon %s init badblock\n",__func__);^M
+ ret = lonbon_set_bad_offset(badblock_number, list_badblock);/* save bad block address*/^M
+ lonbon_printf_bad(3);^M
+ return 0;^M
+^M
+ }else{ /* after the second boot, go here */^M
+ if(badblock_number == lb_badnum){ /* equal means there are no bad blocks */^M
+ printf("lonbon %s not new badblock\n",__func__);^M
+^M
+ }else{ /* unequal means there are bad blocks */^M
+ printf("%s new badblock number= %d\n",__func__, badblock_number - lb_badnum);^M
+ ret = lonbon_set_badnum(badblock_number);^M
+ if(ret < 0){^M
+ printf("error %s badblock_number=null\n",__func__);^M
+ }else{^M
+ new_badblock = true; /* mark the newly added bad block symbol */^M
+ }^M
+ }^M
+ }^M
+^M
+ if(new_badblock == true ){/* there are new bad blocks added */^M
+ /* Get env bad block address */^M
+ ret = lonbon_get_bad_offset(badblock_number, list_badblock ,badblock_number - lb_badnum);^M
+^M
+ for(i=0; i< badblock_number - lb_badnum; i++){^M
+ memset(part_name,0,sizeof(part_name));^M
+ lonbon_get_partitions_name((uint *) badblock_list[i], part_name_t, &lbflash_offset, &lbflash_size);^M
+ ret = lonbon_set_partitions(lb_bad_partition_r, part_name_t);^M
+ }^M
+ printf("%s new_badblock=true\n",__func__);^M
+^M
+ }^M
+^M
+ lonbon_printf_bad_block(lb_bad_partition_r, badblock_number, bad_list_t, badblock_number - lb_badnum, list_badblock);^M
+^M
+ if(new_badblock == true){/* if a new bad block is added, restart and enter restore mode */^M
+ ret = lonbon_set_bad_offset(badblock_number, bad_list_t);/* save bad block address */^M
+ new_badblock = false;^M
+ run_command("reset", 0);^M
+ }^M
+ return 0;^M
+}^M
diff --git a/boot/common/cmd_mtdparts.c b/boot/common/cmd_mtdparts.c
index f6940a6f2..172750152 100755
--- a/boot/common/cmd_mtdparts.c
+++ b/boot/common/cmd_mtdparts.c
@@ -1331,6 +1331,63 @@ int lonbon_get_partitions(const char *part_name, uint *part_offset, uint *part_s}return -1;}
+
+int lonbon_strcpy_name(char *part_name,char *name)
+{
+ char str[10];
+ int len,i;
+ strcpy(str,name);
+ len = strlen(str);
+ for(i=0; i < len; i++){
+ *(part_name+i) = str[i];
+ }
+ return 0;
+}
+/**
+* obtain the partition name of the address by passing it through.
+*/
+
+int lonbon_get_partitions_name(uint *off, char *part_name, uint *part_offset, uint *part_size)
+{
+ struct list_head *dentry, *pentry;
+ struct part_info *part;
+ struct mtd_device *dev;
+ int part_num;
+ uint *part_offset_closure;
+
+ if (!part_name) {
+ printf("the part name is empty\n");
+ //return -1;
+ }
+
+ if (list_empty(&devices)) {
+ printf("the partitions list is empty\n");
+ return -1;
+ }
+
+ if (mtdparts_init() != 0)
+ return -1;
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+ part_num = 0;
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+ //printf("%2d:%s 0x%08llx 0x%08llx\n",part_num, part->name, part->size,part->offset);
+ part_offset_closure = part->offset + part->size;
+ if(part_offset_closure > off){
+
+ lonbon_strcpy_name(part_name,part->name);
+ *part_offset = part->offset;
+ *part_size = part->size;
+ return 0;
+ }
+ part_num++;
+ }
+ }
+ return -1;
+}
+#endif/*** Format and print out a partition list for each device from global device
diff --git a/boot/common/cmd_nand.c b/boot/common/cmd_nand.c
index 64b0bd26b..022696de3 100755
--- a/boot/common/cmd_nand.c
+++ b/boot/common/cmd_nand.c
@@ -718,10 +718,14 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])nand = &nand_info[dev];if (strcmp(cmd, "bad") == 0) {
- printf("\nDevice %d bad blocks:\n", dev);
+ int j = 0;
+ //printf("\nDevice %d bad blocks:\n", dev);for (off = 0; off < nand->size; off += nand->erasesize)
- if (nand_block_isbad(nand, off))
+ if (nand_block_isbad(nand, off)){printf(" %08llx\n", (unsigned long long)off);
+ j++;
+ }
+ printf("bad number %d blocks:\n", j);return 0;}@@ -1466,6 +1470,31 @@ static int lb_nand_erase(uint start_addr, uint part_size, uint length)return 0;}
+#define BADBLOCK_MAX 200
+int lb_nand_get_badblock_number(ulong *badblock_list)
+{
+ int j = 0;
+ ulong off,badblock_addr[BADBLOCK_MAX];
+ nand_info_t *nand = &nand_info[0];
+ char commandline[16];
+ char badb_addr[1024];
+ memset(badblock_addr,0,sizeof(badblock_addr));
+ memset(commandline,0,sizeof(commandline));
+ memset(badb_addr,0,sizeof(badb_addr));
+ printf("\n");
+ for (off = 0; off < nand->size; off += nand->erasesize)
+ if (nand_block_isbad(nand, off)){
+ //printf("lonbon bad blocks %08llx\n", (unsigned long long)off);
+ badblock_addr[j] = off;
+ j++;
+ }
+ printf("\n");
+ for(int i = 0; i < j; i++){
+ //printf("\nlonbon %08lx\n", badblock_addr[i]);
+ badblock_list[i] = badblock_addr[i];
+ }
+ return j;
+}int lb_nand_flash_partition_baseAddr(const char *part_name, uint *part_offset, uint *part_size){
@@ -1492,7 +1521,7 @@ int lb_nand_flash_partition_read(const char *part_name,char* buff,const int lengreturn -1;}- ret=lb_nand_read(lbflash_offset,lbflash_size, length>lbflash_size?lbflash_size:len,(void *) buff);
+ ret = lb_nand_read(lbflash_offset,lbflash_size, length>lbflash_size?lbflash_size:len,(void *) buff);//_print_hex_string(buff,length); //TEST ONLYreturn ret;}
diff --git a/boot/include/configs/infinity2m.h b/boot/include/configs/infinity2m.h
index c5d5d8ea1..19a44747b 100755
--- a/boot/include/configs/infinity2m.h
+++ b/boot/include/configs/infinity2m.h
@@ -39,6 +39,7 @@#define LONBONVOIP#ifdef LONBONVOIP#define CONFIG_CMD_LBCHK
+#define CONFIG_CMD_LBBAD#define CONFIG_LB_MD5#define CONFIG_IDENT_STRING " LonBon Technology "#define LONBONVOIP_REALM "voip.lonbon.com"
========================================================================
第一次开机

第二次开机

第N次开机后产生新坏块

相关文章:
ssd202d-badblock-坏块检测
这边文章讲述的是坏快检测功能 思路: 1.第一次烧录固件会实现跳坏块,但是后续使用会导致坏块的产生; 于是我在uboot环境变量添加了两个变量来控制坏快 lb_badnum //坏块个数 lb_badoff //坏块所在位置 2.第一次开机会根据lb_badnum是否…...
MySQL-练习-数据介绍
文章目录 一. 数据介绍1. 数据结构2. 创建数据库,数据表3. 员工表(employees)练习1 4. 顾客表(customers)练习2 5. 商品(products)和商品类别(categories)表练习3 6. 供应商表(suppliers)练习4 7. 订单和订单明细表练习5 二. 数据汇总三. 使用CASE WHEN …...
React框架:解锁现代化Web开发的新维度
在当今前端开发领域,React 无疑是一颗璀璨的明星。React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库,它在前端开发中占据着重要的地位,为开发者提供了一种高效、灵活且可维护的方式来构建复杂的用户界面。 一、React 的背景与开…...
电阻功率,限流,等效电阻
1 电阻额定功率 2 电阻限流作用 3 电阻并联等效电阻...
Qt | 开发工具(top1)
Qt Creator 跨平台、完整的集成开发环境(IDE),供应用程序开发者创建用于多个桌面、嵌入式和移动设备平台的应用程序。 Qt Linguist 一套将Qt C和Qt Quick应用程序翻译成本地语言的工具。 qmake Qt自动化构建工具,简化了不同平台的构建过程。…...
Node.js express
1. express 介绍 express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs.com.cn/简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用ÿ…...
ios h5中在fixed元素中的input被focus时,键盘遮挡input (van-popup、van-feild)
问题描述: 前提:我使用的是vant组件库,其中一个页面中有一个van-popup组件,van-popup组件中又嵌套了一个van-field组件预期结果:当点击van-feild输入框时,键盘弹起,输入框显示在键盘上方实际结…...
springboot整合lua脚本在Redis实现商品库存扣减
1、目的 使用lua脚本,可以保证多条命令的操作原子性;同时可以减少操作IO(比如说判断redis对应数据是否小于0,小于0就重置为100,这个场景一般是取出来再判断,再存放进行,就至少存在2次IO,用lua脚…...
MySQL ON DUPLICATE KEY UPDATE影响行数
目录 分析为什么Updates返回7 总结 数据库更新日志如下 insertOrUpdateList|> Preparing: INSERT INTO clue_user_tag (vuid, tag_id, tag_type, content) VALUES (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) , (?, ?, ?, ?) ON DUPLICATE KEY UPDATE …...
uniapp小程序 slot中无法传递外部参数的解决方案
最近在封装一个List组件,外部传给我数据,我循环后将每个Item部分slot到外部,由调用者自己去写item布局,类似ElementUI、iView的Tabe列表。 List: <view v-if"list.length > 0" class"list-scroll__item&quo…...
umi实现动态获取菜单权限
文章目录 前景登录组件编写登录逻辑菜单的时机动态路由页面刷新手动修改地址 前景 不同用户拥有不同的菜单权限,现在我们实现登录动态获取权限菜单。 登录组件编写 //当我们需要使用dva的dispatch函数时,除了通过connect函数包裹组件还可以使用这种方…...
Pytest-Bdd-Playwright 系列教程(14):Docstring 参数
Pytest-Bdd-Playwright 系列教程(14):Docstring 参数 前言一、什么是docstring?二、基本语法三、主要特点四、实际例子五、注意事项六、使用建议总结 前言 在自动化测试的过程中,我们经常需要处理复杂的测试数据或需要输入多行文…...
交互开发---测量工具(适用VTK或OpenGL开发的应用程序)
简介: 经常使用RadiAnt DICOM Viewer来查看DICOM数据,该软件中的测量工具比较好用,就想着仿照其交互方式自己实现下。后采用VTK开发应用程序时,经常需要开发各种各样的测量工具,如果沿用VTK的widgets的思路,…...
Qt 一个简单的QChart 绘图
Qt 一个简单的QChart 绘图 先上程序运行结果图: “sample9_1QChart.h” 文件代码如下: #pragma once#include <QtWidgets/QMainWindow> #include "ui_sample9_1QChart.h"#include <QtCharts> //必须这么设置 QT_CHARTS_USE_NAME…...
【Java笔记】LinkedList 底层结构
一、LinkedList 的全面说明 LinkedList底层实现了双向链表和双端队列特点可以添加任意元素(元素可以重复),包括null线程不安全,没有实现同步 二、LinkedList 的底层操作机制 三、LinkedList的增删改查案例 public class LinkedListCRUD { public stati…...
el-table组件树形数据修改展开箭头
<style lang"scss" scoped> ::v-deep .el-table__expand-icon .el-icon-arrow-right:before {content: ">"; // 箭头样式font-size: 16px; }::v-deep .el-table__expand-icon{ // 没有展开的状态background-color: rgba(241, 242, 245, 1);color:…...
太速科技-FMC154-基于FMC 八路SFP+万兆光纤子卡
FMC154-基于FMC 八路SFP万兆光纤子卡 一、板卡概述 本卡是一个FPGA夹层卡(FMC)模块,可提供高达8个SFP / SFP 模块接口,直接插入千兆位级收发器(MGT)的赛灵思FPGA。支持业界标准的小型可插拔࿰…...
记:排查设备web时慢时快问题,速度提升100%
问题描述 问题1: 发现web登录界面刷新和登录功能都比较卡,开浏览器控制台看了下,让我很惊讶,居然能这么慢: 公司2个局域网内的表现不同,局域网A中的都比较卡,局域网B中的又不存在该现象。 问…...
音视频入门基础:MPEG2-TS专题(13)——FFmpeg源码中,解析Section Header的实现
一、引言 在《音视频入门基础:MPEG2-TS专题(11)—— TS中的Section》中讲述了Section Header的基本概念,本文讲述FFmpeg源码中是怎样解析Section Header的。 二、parse_section_header函数的定义 FFmpeg源码中通过parse_section…...
根据PDF模板单个PDF导出到浏览器和多个PDF打包ZIP导出到浏览器
一、单个PDF导出到浏览器 /*** * param templatePath 模板路径* param fileName 文件名称* param data 填充文本* param images 填充图片* param response* throws IOException*/public static void generateTempPDF(String templatePath, String fileName, Map<String, S…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
小木的算法日记-多叉树的递归/层序遍历
🌲 从二叉树到森林:一文彻底搞懂多叉树遍历的艺术 🚀 引言 你好,未来的算法大神! 在数据结构的世界里,“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的,它…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema,不需要复杂的查询,只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 :在几秒钟…...
简约商务通用宣传年终总结12套PPT模版分享
IOS风格企业宣传PPT模版,年终工作总结PPT模版,简约精致扁平化商务通用动画PPT模版,素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...
