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…...
如何创建一个基本的Spring Boot应用程序
以下是一个简单的Spring Boot应用开发代码示例,它展示了如何创建一个基本的Spring Boot应用程序,并实现一个简单的RESTful API服务。 步骤1:创建项目 使用Spring Initializr或您喜欢的IDE(如IntelliJ IDEA或Eclipse)…...
1.2 计算机网络的分类和应用(重要知识点)
1.2.1 计算机网络的分类 计算机网络的定义: 由通信线路互相连接的、能自主工作的计算机构成,强调各计算机(工作站)拥有独立的计算资源和任务能力。与多终端分时系统不同,后者终端仅作为主机接口,不具备计…...
@JsonSerialize失效解决
当在实体类中加入这个注解时,本意是想如果是空值则返回0给页面,但是发现使用 JsonSerialize(using BigSerializer.class)无效,因为如果是null值会不走序列化的接口实现类,需要使用nullUsing 需要这样使用...
Docker部署WebRTC-Streamer
文章目录 WebRTC-Streamer概述Docker部署WebRTC-StreamerVue使用WebRTC-Streamer一些问题 WebRTC-Streamer概述 WebRTC-Streamer是一个基于WebRTC技术的流媒体传输工具,它可以通过Web浏览器实现实时音视频流的传输和播放。它提供了一种简单而强大的方式ÿ…...
2025年的大模型计划重点在于跨领域智能、工作流自动化、多模态能力强化
明年的计划和大模型发展方向可以围绕以下几个方面展开,结合实际应用场景和技术趋势,明确可执行的目标和期待的成果: 2025 年计划与展望:大模型能做些什么? 1. 更深层次的跨领域能力融合 目标:构建更强的跨…...
day12 接口测试 ——入门→精通→实战(1)
【没有所谓的运气🍬,只有绝对的努力✊】 目录 1、接口测试分类 1.1 内部接口: 1.2 外部接口: 2、目前接口架构设计 2.1、基于SOAP架构, 2.2、基于RPC架构, 2.3、基于RestFul架构, 2.3.1…...
伏羲0.07(文生图)
为了使0.06代码能够有效运行并输出项目目录及所有文件,我们在代码中添加一些额外的功能。 项目目录结构 项目目录结构如下: text_to_image_project/ │ ├── config.yaml ├── data/ │ ├── train_data.csv │ └── test_data.txt ├── mod…...
scala的泛型特质的应用场景
//泛型特质的应用场景 //作比较找出最大值 //定义一个函数,用来求List元素中的最大值参考代码:object Test4 {def getMax[T](list:List[T])(implicit ev:T > Ordered[T]): T {list.reduce((a:T,b:T)> if(a>b) a else b)}def main(args: Array…...
Win10环境vscode+latex+中文快速配置
安装vscodelatex workshop 配置: {"liveServer.settings.donotVerifyTags": true,"liveServer.settings.donotShowInfoMsg": true,"explorer.confirmDelete": false,"files.autoSave": "afterDelay","exp…...
【vue2】el-select,虚拟滚动(vue-virtual-scroller)
需求背景 vue2+element-ui项目中,当el-select中数据量较大时(超出5000个dom节点),会导致页面加载和渲染卡顿、el-select下拉列表延迟展开。 在现在的el-select的基础上使用分页或者虚拟列表的形式去处理大量的下拉菜单,可以保证页面的正常渲染及el-select的…...
做伊瑞尔竞技场的网站/网络营销的概述
解决方案: 1、尝试用绝对函数方法调用: 如 local a A.a or {}; function a:Max(pa, pb) end--使用方法: A.a:Max(1,2); 2.那就还说明一个问题,该函数没注册上,看看是不是写函数时头文件未包含,又或者敲代…...
装修招标网站/宁波seo外包平台
2019独角兽企业重金招聘Python工程师标准>>> git clone gitubuntu-12.04-LTS:gitolite-admin.git 如果克隆失败,需要 git clone gitubuntu-12.04-LTS:repositories/gitolite-admin.git 即可, 如果还是失败, 需要 git clone gitubuntu-12.04-L…...
网站建设指引/企业网站seo优化外包
VBO与Displaylists的进一步讨论 Posted on 2006-04-21 22:50 panhongwei 阅读(257) 评论(0) 编辑 收藏 所属分类: 大规模地形渲染 之前写的关于VBO与Displaylists的讨论不是很详细,现在重新整理一下,不过需要注意的我的测试结果是在没做view frustum cu…...
网站建设分析报告/搜一搜
note:本文短代码实现环境:win10,python3 本文代码执行情况 python打开浏览器方法一: 通过引用os包,调用system方法调用系统的ie程序来打开网址 代码如下: import os os.system("C:/Program Files/Internet Explorer/iexplore…...
芜湖有没有做网站的/原版百度
HDFS的写入过程 1)客户端向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在。 2)namenode返回是否可以上传。如果可以上传,客户端给上传文件做逻辑分块。 3)客户端请求第一个 block上传到哪几…...
美女做直播网站有哪些/关键词数据分析工具有哪些
Apache Kafka是一个高性能、高可用性、冗余的流消息平台。Kafka的功能很像发布/订阅消息系统,但具有更高的吞吐量、内置分区、复制和容错能力。对于大规模消息处理应用程序来说,Kafka是一个很好的解决方案。它通常与Apache Hadoop和Spark Streaming一起使…...