[U-Boot-Users] [PATCH] add explicit bbt creation to commandline

[PATCH] add explicit bbt creation to commandline ("nand createbbt" command)
This patch adds user-requested BBT creation. It includes the following changes:
- common/cmd_nand.c: move yes/no decision to separate function - do_nand: ask for confirmation for "nand erase" - do_nand: add command "nand createbbt" to erase NAND and create a new BBT
Signed-off-by: Werner Almesberger werner@openmoko.org Signed-off-by: Harald Welte laforge@openmoko.org
---
diff --git a/common/cmd_nand.c b/common/cmd_nand.c index bb46f34..2f41157 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -162,6 +162,17 @@ out: return 0; }
+static int yes(void) +{ + char c; + + c = getc(); + if (c != 'y' && c != 'Y') + return 0; + c = getc(); + return c == '\r' || c == '\n'; +} + int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i, dev, ret; @@ -231,7 +242,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && strcmp(cmd, "biterr") != 0 && - strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 ) + strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 && + strcmp(cmd, "createbbt") != 0 ) goto usage;
/* the following commands operate on the current device */ @@ -286,13 +298,23 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) "are sure of what you are doing!\n" "\nReally scrub this NAND flash? <y/N>\n");
- if (getc() == 'y' && getc() == '\r') { + if (yes()) { opts.scrub = 1; } else { puts("scrub aborted\n"); return -1; } } + else { + if (opts.length == nand->size) { + puts("Really erase everything ? <y/N>\n"); + if (!yes()) { + puts("erase aborted\n"); + return -1; + } + } + } + ret = nand_erase_opts(nand, &opts); printf("%s\n", ret ? "ERROR" : "OK");
@@ -461,6 +483,33 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 0; }
+ if (strcmp(cmd, "createbbt") == 0) { + struct nand_chip *nand_chip = nand->priv; + nand_erase_options_t opts; + + puts("Create BBT and erase everything ? <y/N>\n"); + if (!yes()) { + puts("createbbt aborted\n"); + return -1; + } + memset(&opts, 0, sizeof(opts)); + opts.length = nand->size; + if (nand_erase_opts(nand, &opts)) { + puts("Erase failed\n"); + return 1; + } + nand_chip->options &= ~NAND_DONT_CREATE_BBT; + puts("Creating BBT. Please wait ..."); + if (nand_default_bbt(nand)) { + puts("\nFailed\n"); + return 1; + } + else { + puts("\n"); + return 0; + } + } + usage: printf("Usage:\n%s\n", cmdtp->usage); return 1; @@ -481,7 +530,8 @@ U_BOOT_CMD(nand, 5, 1, do_nand, "nand markbad off - mark bad block at offset (UNSAFE)\n" "nand biterr off - make a bit error at offset (UNSAFE)\n" "nand lock [tight] [status] - bring nand to lock state or display locked pages\n" - "nand unlock [offset] [size] - unlock section\n"); + "nand unlock [offset] [size] - unlock section\n" + "nand createbbt - create bad block table\n");
static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, ulong offset, ulong addr, char *cmd) diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 27d5988..3fdc25a 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -795,7 +795,8 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
len = mtd->size >> (this->bbt_erase_shift + 2); /* Allocate memory (2bit per block) */ - this->bbt = kmalloc (len, GFP_KERNEL); + if (!this->bbt) + this->bbt = kmalloc (len, GFP_KERNEL); if (!this->bbt) { printk (KERN_ERR "nand_scan_bbt: Out of memory\n"); return -ENOMEM;

On 16:04 Sun 06 Jul , Harald Welte wrote:
[PATCH] add explicit bbt creation to commandline ("nand createbbt" command)
This patch adds user-requested BBT creation. It includes the following changes:
- common/cmd_nand.c: move yes/no decision to separate function
- do_nand: ask for confirmation for "nand erase"
- do_nand: add command "nand createbbt" to erase NAND and create a new BBT
Signed-off-by: Werner Almesberger werner@openmoko.org Signed-off-by: Harald Welte laforge@openmoko.org
diff --git a/common/cmd_nand.c b/common/cmd_nand.c index bb46f34..2f41157 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -162,6 +162,17 @@ out: return 0; }
+static int yes(void) +{
- char c;
- c = getc();
- if (c != 'y' && c != 'Y')
return 0;
- c = getc();
- return c == '\r' || c == '\n';
+}
It will be good to have it in a re-usable header as inline.
And why not name it as "ask_confirm()"?
Best Regards, J.

In message 20080706111620.GC13922@game.jcrosoft.org you wrote:
+static int yes(void) +{
- char c;
- c = getc();
- if (c != 'y' && c != 'Y')
return 0;
- c = getc();
- return c == '\r' || c == '\n';
+}
It will be good to have it in a re-usable header as inline.
And why not name it as "ask_confirm()"?
Or extend it a bit and call it ckyorn() - oh, good old SVR4 times :-)
Best regards,
Wolfgang Denk

On Sun, Jul 06, 2008 at 04:04:56PM +0800, Harald Welte wrote:
- do_nand: ask for confirmation for "nand erase"
This will break any usage in scripts. At least, have an explicit command such as "nand erase all" that doesn't ask.
- do_nand: add command "nand createbbt" to erase NAND and create a new BBT
Please do any new NAND development against the u-boot-nand-flash testing tree (and CC me and include "NAND" in the subject on any NAND patches).
-Scott

Hi, I know this message is about 18 months old. I am using Uboot 2008.10, which seems to not include support for creating the Nand BBT (bad block table). Was this patch released and if so when? Forgive me as I don't know how to find out.
How best to add BBT support to Uboot? I need to have a BBT created such that Linux can use it when it loads.
I hope you can help.
Thanks in advance, Steve P.S.: I snipped out portions of this code to save space in this reply.
Harald Welte wrote:
[PATCH] add explicit bbt creation to commandline ("nand createbbt" command)
This patch adds user-requested BBT creation. It includes the following changes:
- common/cmd_nand.c: move yes/no decision to separate function
- do_nand: ask for confirmation for "nand erase"
- do_nand: add command "nand createbbt" to erase NAND and create a new BBT
Signed-off-by: Werner Almesberger werner@openmoko.org Signed-off-by: Harald Welte laforge@openmoko.org
diff --git a/common/cmd_nand.c b/common/cmd_nand.c index bb46f34..2f41157 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -162,6 +162,17 @@ out: return 0; }
+static int yes(void) +{
- char c;
- c = getc();
- if (c != 'y' && c != 'Y')
return 0;
- c = getc();
- return c == '\r' || c == '\n';
+}
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) { int i, dev, ret; @@ -231,7 +242,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 && strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 && strcmp(cmd, "biterr") != 0 &&
strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 &&
strcmp(cmd, "createbbt") != 0 )
goto usage;
/* the following commands operate on the current device */
@@ -286,13 +298,23 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) "are sure of what you are doing!\n" "\nReally scrub this NAND flash? <y/N>\n");
if (getc() == 'y' && getc() == '\r') {
}if (yes()) { opts.scrub = 1; } else { puts("scrub aborted\n"); return -1; }
else {
if (opts.length == nand->size) {
puts("Really erase everything ? <y/N>\n");
if (!yes()) {
puts("erase aborted\n");
return -1;
}
}
}
- ret = nand_erase_opts(nand, &opts); printf("%s\n", ret ? "ERROR" : "OK");
@@ -461,6 +483,33 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 0; }
- if (strcmp(cmd, "createbbt") == 0) {
struct nand_chip *nand_chip = nand->priv;
nand_erase_options_t opts;
puts("Create BBT and erase everything ? <y/N>\n");
if (!yes()) {
puts("createbbt aborted\n");
return -1;
}
memset(&opts, 0, sizeof(opts));
opts.length = nand->size;
if (nand_erase_opts(nand, &opts)) {
puts("Erase failed\n");
return 1;
+. . . snip.... . . .

On Thu, Feb 11, 2010 at 06:49:33PM -0800, Steven Zedeck wrote:
Hi, I know this message is about 18 months old. I am using Uboot 2008.10, which seems to not include support for creating the Nand BBT (bad block table). Was this patch released and if so when? Forgive me as I don't know how to find out.
How best to add BBT support to Uboot? I need to have a BBT created such that Linux can use it when it loads.
U-Boot supports creating a bad block table in flash, and has done so since before 2008.10 (assuming you're not using legacy NAND). Whether it does this depends on whether the NAND driver requests it with NAND_BBT_CREATE in nand_bbt_descr.options and NAND_USE_FLASH_BBT in nand_chip.options.
Linux can also create this table. Either way, it only needs to be done once, not on every boot.
What the patch you quote does, as far as I can tell without what's been snipped, is allow a new bad block table to be created when erasing the entire chip. Normally the bad block table would be excluded from a full-chip erase.
-Scott

Hi, I know this message is about 18 months old. I am using Uboot 2008.10, which seems to not include support for creating the Nand BBT (bad block table). Was this patch released and if so when? Forgive me as I don't know how to find out.
How best to add BBT support to Uboot? I need to have a BBT created such that Linux can use it when it loads.
U-Boot supports creating a bad block table in flash, and has done so since before 2008.10 (assuming you're not using legacy NAND). Whether it does this depends on whether the NAND driver requests it with NAND_BBT_CREATE in nand_bbt_descr.options and NAND_USE_FLASH_BBT in nand_chip.options.
I REALLY appreciate your help. I see in drivers/mtd/nand/nand_bbt.c where it checks for NAND_BBT_CREATE. What I don't see is where/how this gets set. Is there a config file that sets this?
thanks, Steve
Linux can also create this table. Either way, it only needs to be done once, not on every boot.
What the patch you quote does, as far as I can tell without what's been snipped, is allow a new bad block table to be created when erasing the entire chip. Normally the bad block table would be excluded from a full-chip erase.

Steven Zedeck wrote:
U-Boot supports creating a bad block table in flash, and has done so since before 2008.10 (assuming you're not using legacy NAND). Whether it does this depends on whether the NAND driver requests it with NAND_BBT_CREATE in nand_bbt_descr.options and NAND_USE_FLASH_BBT in nand_chip.options.
I REALLY appreciate your help. I see in drivers/mtd/nand/nand_bbt.c where it checks for NAND_BBT_CREATE. What I don't see is where/how this gets set. Is there a config file that sets this?
It is set in the BBT descriptor struct. Which NAND driver are you using? In order for it not to be set, the driver would have to use a non-default BBT descriptor (for bbt_td/bbt_md, not badblock_pattern) and leave out that flag. I don't see any upstream drivers (at least not under drivers/mtd/nand) that do that, so it should just be a matter of whether the driver specifies NAND_USE_FLASH_BBT in chip->options.
-Scott

U-Boot supports creating a bad block table in flash, and has done so since before 2008.10 (assuming you're not using legacy NAND). Whether it does this depends on whether the NAND driver requests it with NAND_BBT_CREATE in nand_bbt_descr.options and NAND_USE_FLASH_BBT in nand_chip.options.
I REALLY appreciate your help. I see in drivers/mtd/nand/nand_bbt.c where it checks for NAND_BBT_CREATE. What I don't see is where/how this gets set. Is there a config file that sets this?
It is set in the BBT descriptor struct. Which NAND driver are you using? In order for it not to be set, the driver would have to use a non-default BBT descriptor (for bbt_td/bbt_md, not badblock_pattern) and leave out that flag. I don't see any upstream drivers (at least not under drivers/mtd/nand) that do that, so it should just be a matter of whether the driver specifies NAND_USE_FLASH_BBT in chip->options.
First of all, I inherited much of this code, especially the NAND-related stuff. I've never needed to go into this portion of the code.
It seems we are using the mtd driver as all our files dealing with nand are in drivers/mtd/nand. The only place I see NAND_USE_FLASH_BBT being used is in nand_bbt.c in nand_default_bbt. I see this:
this->options |= NAND_USE_FLASH_BBT; return nand_scan_bbt (mtd, &agand_flashbased);
Is this what you are referring to?
Also, once we get the BBT created, does the code that loads Linux use that info ?
Thanks a million. Steve

Steven Zedeck wrote:
First of all, I inherited much of this code, especially the NAND-related stuff. I've never needed to go into this portion of the code.
It seems we are using the mtd driver as all our files dealing with nand are in drivers/mtd/nand. The only place I see NAND_USE_FLASH_BBT being used is in nand_bbt.c in nand_default_bbt. I see this:
this->options |= NAND_USE_FLASH_BBT; return nand_scan_bbt (mtd, &agand_flashbased);
Is this what you are referring to?
No, I mean in the NAND driver for your specific hardware (fsl_elbc_nand.c, mxc_nand.c, ndfc_nand.c, etc).
Also, once we get the BBT created, does the code that loads Linux use that info ?
The BBT is created on the flash. Linux runs pretty much the same code as u-boot and will use the on-flash BBT if its NAND driver specifies NAND_USE_FLASH_BBT. This isn't about in-memory BBTs.
-Scott

No, I mean in the NAND driver for your specific hardware (fsl_elbc_nand.c, mxc_nand.c, ndfc_nand.c, etc).
You have been so helpful. I looked at the mtd/nand/Makefile and the only file that's included besides the nand* files is:
COBJS-y += fsl_upm.o
However, in that code: #if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_FSL_UPM)
But I don't see CONFIG_NAND_FSL_UPM defined anywhere. It seems that this file really isn't being used.
How do I determine what hadrware driver its using? I'm sure this sounds like a dumb question. Do all the drivers live in drivers/mtd/nand/.... ?
thanks, Steve

Steven Zedeck wrote:
No, I mean in the NAND driver for your specific hardware (fsl_elbc_nand.c, mxc_nand.c, ndfc_nand.c, etc).
You have been so helpful. I looked at the mtd/nand/Makefile and the only file that's included besides the nand* files is:
COBJS-y += fsl_upm.o
However, in that code: #if defined(CONFIG_CMD_NAND) && defined(CONFIG_NAND_FSL_UPM)
But I don't see CONFIG_NAND_FSL_UPM defined anywhere. It seems that this file really isn't being used.
How do I determine what hadrware driver its using? I'm sure this sounds like a dumb question. Do all the drivers live in drivers/mtd/nand/.... ?
thanks, Steve
I think we are just using the base/generic mtd nand driver. Is that possible?
thanks, Steve

Steven Zedeck wrote:
Steven Zedeck wrote:
No, I mean in the NAND driver for your specific hardware (fsl_elbc_nand.c, mxc_nand.c, ndfc_nand.c, etc).
You have been so helpful. I looked at the mtd/nand/Makefile and the only file that's included besides the nand* files is:
COBJS-y += fsl_upm.o
You've got an old/out-of-tree u-boot.
I think we are just using the base/generic mtd nand driver. Is that possible?
No, there must be a controller driver. It may be in a board or cpu directory, though. Search for board_nand_init().
-Scott

Scott Wood-2 wrote:
Steven Zedeck wrote:
Steven Zedeck wrote:
No, I mean in the NAND driver for your specific hardware (fsl_elbc_nand.c, mxc_nand.c, ndfc_nand.c, etc).
You have been so helpful. I looked at the mtd/nand/Makefile and the only file that's included besides the nand* files is:
COBJS-y += fsl_upm.o
You've got an old/out-of-tree u-boot.
I think we are just using the base/generic mtd nand driver. Is that possible?
No, there must be a controller driver. It may be in a board or cpu directory, though. Search for board_nand_init().
Its in board/atmel/at91sam9rlek/nand.c
It doesn't do much but set up the various GPIO connections. Here's the function:
int board_nand_init(struct nand_chip *nand) { nand->ecc.mode = NAND_ECC_SOFT; #ifdef CFG_NAND_DBW_16 nand->options = NAND_BUSWIDTH_16; #endif nand->cmd_ctrl = at91sam9rlek_nand_hwcontrol; nand->dev_ready = at91sam9rlek_nand_ready; nand->chip_delay = 20;
return 0; }
thanks, Steve

On Fri, Feb 12, 2010 at 06:14:51PM -0800, Steven Zedeck wrote:
Its in board/atmel/at91sam9rlek/nand.c
It doesn't do much but set up the various GPIO connections. Here's the function:
int board_nand_init(struct nand_chip *nand) { nand->ecc.mode = NAND_ECC_SOFT; #ifdef CFG_NAND_DBW_16 nand->options = NAND_BUSWIDTH_16; #endif nand->cmd_ctrl = at91sam9rlek_nand_hwcontrol; nand->dev_ready = at91sam9rlek_nand_ready; nand->chip_delay = 20;
return 0; }
Add "nand->options |= NAND_USE_FLASH_BBT;".
-Scott

Scott Wood-2 wrote:
On Fri, Feb 12, 2010 at 06:14:51PM -0800, Steven Zedeck wrote:
Its in board/atmel/at91sam9rlek/nand.c
It doesn't do much but set up the various GPIO connections. Here's the function:
int board_nand_init(struct nand_chip *nand) { nand->ecc.mode = NAND_ECC_SOFT; #ifdef CFG_NAND_DBW_16 nand->options = NAND_BUSWIDTH_16; #endif nand->cmd_ctrl = at91sam9rlek_nand_hwcontrol; nand->dev_ready = at91sam9rlek_nand_ready; nand->chip_delay = 20;
return 0; }
Add "nand->options |= NAND_USE_FLASH_BBT;".
-Scott
Scott, I really appreciate your help. I added what you suggested, except since we are using an 8 bit wide bus and not 16 I had to do the following:
#ifdef CFG_NAND_DBW_8 nand->options |= NAND_USE_FLASH_BBT; #endif
CFG_NAND_DBW_8 is set in my configs.h file.
Now when my board boots I get this and then it just stops: NAND: Entering nand_init Nand Base 0x40000000 Bad block table not found for chip 0 Bad block table not found for chip 0
That comes from nand_bbt.c Clearly there is something I'm missing regarding how the BBT is created and utilized in Uboot.
thanks, Steve

Steven Zedeck wrote:
Scott Wood-2 wrote:
On Fri, Feb 12, 2010 at 06:14:51PM -0800, Steven Zedeck wrote:
int board_nand_init(struct nand_chip *nand) { nand->ecc.mode = NAND_ECC_SOFT; #ifdef CFG_NAND_DBW_16 nand->options = NAND_BUSWIDTH_16; #endif nand->cmd_ctrl = at91sam9rlek_nand_hwcontrol; nand->dev_ready = at91sam9rlek_nand_ready; nand->chip_delay = 20;
return 0; }
Add "nand->options |= NAND_USE_FLASH_BBT;".
[snip]
I really appreciate your help. I added what you suggested, except since we are using an 8 bit wide bus and not 16 I had to do the following:
#ifdef CFG_NAND_DBW_8 nand->options |= NAND_USE_FLASH_BBT; #endif
I don't see why the ifdef is needed -- just don't put it inside (or before) the other ifdef.
Now when my board boots I get this and then it just stops: NAND: Entering nand_init Nand Base 0x40000000 Bad block table not found for chip 0 Bad block table not found for chip 0
The messages are expected on the first boot -- but it should then create the bad block table.
You'll have to debug to find out why it's hanging. If you don't set NAND_USE_FLASH_BBT, does ordinary nand read/write from the u-boot prompt work?
-Scott
participants (5)
-
Harald Welte
-
Jean-Christophe PLAGNIOL-VILLARD
-
Scott Wood
-
Steven Zedeck
-
Wolfgang Denk