[PATCH 3/3] imx-bbu-nand-fcb: Add command to help debug FCB issues

Trent Piepho trent.piepho at igorinstitute.com
Mon Oct 11 18:53:59 PDT 2021


Add new "fcb" command.  It can save a decoded copy of the FCB to a file,
do a hexdump of the decoded FCB, or display the FCB fields.  Or simply
read and validate the FCB.

The FCB uses a different ECC system that the rest of flash and there is
no easy way to decode it in Barebox or Linux.  The code already here
does it.

This will also set the nand0.barebox device parameters with the location
of the bootloader images as read from the FCB.

Signed-off-by: Trent Piepho <trent.piepho at igorinstitute.com>
---
 commands/Kconfig          |  19 ++++++
 common/imx-bbu-nand-fcb.c | 126 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 139 insertions(+), 6 deletions(-)

diff --git a/commands/Kconfig b/commands/Kconfig
index 5ae3cb3dd..d3b5cd7fa 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -277,6 +277,25 @@ config CMD_SLICE
 	  command can be used to print informations about slices and also to manipulate
 	  them on the command line for debugging purposes.
 
+config CMD_IMX_NAND_FCB
+	tristate
+	prompt "iMX FCB decoding and display"
+	depends on BAREBOX_UPDATE_IMX_NAND_FCB
+	help
+	  Decode and display or save the contents of the iMX FCB.
+
+	  This will add a command named "fcb" that will decode the FCB and can
+	  save the decode data to a file or display the contents.
+
+	  The FCB is a block of data at the start of NAND flash that instructs
+	  the iMX ROM bootloader on how to find Barebox.  It uses a different
+	  ECC config than the rest of NAND flash and can't be read correctly
+	  with normal "md" commands.
+
+	  The command also saves the locations of the Barebox image in NAND
+	  from the FCB into parameters on the NAND deivce, which are available
+	  in scripts as environment variables.
+
 # end Information commands
 endmenu
 
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 76ac1d4f2..e61494930 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -7,6 +7,8 @@
 
 #include <filetype.h>
 #include <common.h>
+#include <command.h>
+#include <getopt.h>
 #include <malloc.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -14,6 +16,7 @@
 #include <linux/sizes.h>
 #include <bbu.h>
 #include <fs.h>
+#include <libfile.h>
 #include <linux/mtd/mtd-abi.h>
 #include <linux/mtd/nand_mxs.h>
 #include <linux/mtd/mtd.h>
@@ -27,6 +30,9 @@
 #include <mtd/mtd-peb.h>
 #include <soc/imx/imx-nand-bcb.h>
 
+/* Name of NAND device that contains FCB */
+#define FCB_NAND_PART "nand0.barebox"
+
 #ifdef CONFIG_ARCH_IMX6
 #include <mach/imx6.h>
 static inline int fcb_is_bch_encoded(void)
@@ -387,6 +393,7 @@ static ssize_t raw_write_page(struct mtd_info *mtd, void *buf, loff_t offset)
         return ret;
 }
 
+/* Returns size of FCB on success, negative on error */
 static int read_fcb(struct mtd_info *mtd, int num, struct fcb_block **retfcb)
 {
 	int ret;
@@ -403,10 +410,13 @@ static int read_fcb(struct mtd_info *mtd, int num, struct fcb_block **retfcb)
 		goto err;
 	}
 
-	if (fcb_is_bch_encoded())
+	if (fcb_is_bch_encoded()) {
 		fcb = read_fcb_bch(rawpage, 40);
-	else
+		ret = 128 * 8;
+	} else {
 		fcb = read_fcb_hamming_13_8(rawpage);
+		ret = 512;
+	}
 
 	if (IS_ERR(fcb)) {
 		pr_err("Cannot read fcb on block %d\n", num);
@@ -415,7 +425,6 @@ static int read_fcb(struct mtd_info *mtd, int num, struct fcb_block **retfcb)
 	}
 
 	*retfcb = fcb;
-	ret = 0;
 err:
 	free(rawpage);
 
@@ -870,7 +879,7 @@ static int fcb_dbbt_check(struct mtd_info *mtd, int num, struct fcb_block *fcb)
 	int pages_per_block = mtd->erasesize / mtd->writesize;
 
 	ret = read_fcb(mtd, num, &f);
-	if (ret)
+	if (ret < 0)
 		return ret;
 
 	if (memcmp(fcb, f, sizeof(*fcb))) {
@@ -1403,7 +1412,7 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 	imx_handler->filetype = filetype_arm_barebox;
 
 	handler = &imx_handler->handler;
-	handler->devicefile = "nand0.barebox";
+	handler->devicefile = FCB_NAND_PART;
 	handler->name = name;
 	handler->flags = flags | BBU_HANDLER_CAN_REFRESH;
 	handler->handler = imx_bbu_nand_update;
@@ -1480,7 +1489,7 @@ int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
 	imx_handler->filetype = filetype_mxs_bootstream;
 
 	handler = &imx_handler->handler;
-	handler->devicefile = "nand0.barebox";
+	handler->devicefile = FCB_NAND_PART;
 	handler->name = name;
 	handler->flags = flags | BBU_HANDLER_CAN_REFRESH;
 	handler->handler = imx_bbu_nand_update;
@@ -1492,3 +1501,108 @@ int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
 	return ret;
 }
 #endif
+
+#if IS_ENABLED(CONFIG_CMD_IMX_NAND_FCB)
+
+static int do_fcb(int argc, char *argv[])
+{
+	int opt;
+	int fd;
+	int ret;
+	int fcbsize;
+	struct cdev *cdev;
+	struct fcb_block *fcb;
+	bool hex = false, info = false;
+	const char *outfile = NULL;
+	unsigned int block = 0;
+
+	while ((opt = getopt(argc, argv, "xin:o:")) > 0) {
+		switch (opt) {
+		case 'x':
+			hex = true;
+			break;
+		case 'i':
+			info = true;
+			break;
+		case 'o':
+			outfile = optarg;
+			break;
+		case 'n':
+			block = strtoull_suffix(optarg, NULL, 0);
+			break;
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
+
+	if (optind != argc)
+		return COMMAND_ERROR_USAGE;
+
+	cdev = cdev_by_name(FCB_NAND_PART);
+	if (!cdev) {
+		pr_err("Couldn't find FCB flash device '%s'\n", FCB_NAND_PART);
+		return -ENODEV;
+	}
+
+	ret = read_fcb(cdev->mtd, block, &fcb);
+	if (ret < 0) {
+		perror("read_fcb");
+		return ret;
+	}
+	fcbsize = ret;
+	ret = 0;
+	if (!info && !hex && !outfile)
+		printf("FCB OK (%d bytes)\n", fcbsize);
+
+	set_dev_params(cdev, fcb);
+
+	if (info) {
+		const int oldlevel = barebox_loglevel;
+
+		barebox_loglevel = MSG_DEBUG;
+		pr_debug("Decoded FCB size:           %d bytes\n", fcbsize);
+		dump_fcb(fcb);
+		barebox_loglevel = oldlevel;
+	}
+
+	if (hex)
+		memory_display(fcb, 0, fcbsize, 1, 0);
+
+	if (outfile) {
+		fd = open(outfile, O_WRONLY | O_CREAT, 0644);
+		if (fd < 0) {
+			perror("open");
+			ret = fd;
+			goto out;
+		}
+		ret = write_full(fd, fcb, fcbsize);
+		close(fd);
+		if (ret < 0) {
+			perror("write");
+			goto out;
+		}
+	}
+
+out:
+	free(fcb);
+	return ret;
+}
+
+
+BAREBOX_CMD_HELP_START(fcb)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-i", "Print information from FCB")
+BAREBOX_CMD_HELP_OPT("-x", "Display FCB data bytes")
+BAREBOX_CMD_HELP_OPT("-n BLK", "Eraseblock number to read FCB from")
+BAREBOX_CMD_HELP_OPT("-o FILE", "Write decoded FCB to file")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(fcb)
+	.cmd		= do_fcb,
+	BAREBOX_CMD_DESC("i.MX FCB decoder")
+	BAREBOX_CMD_OPTS("[-ixno]")
+	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+	BAREBOX_CMD_HELP(cmd_fcb_help)
+BAREBOX_CMD_END
+
+#endif /*CONFIG_CMD_IMX_NAND_FCB*/
-- 
2.31.1




More information about the barebox mailing list