2 * i.MX6 nand boot control block(bcb).
4 * Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
6 * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
7 * Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
9 * SPDX-License-Identifier: GPL-2.0+
16 #include <jffs2/jffs2.h>
17 #include <linux/mtd/mtd.h>
19 #include <asm/mach-imx/imx-nandbcb.h>
20 #include <asm/mach-imx/imximage.cfg>
22 #include <linux/mtd/mtd.h>
25 #define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
26 #define GETBIT(v, n) (((v) >> (n)) & 0x1)
28 static u8 calculate_parity_13_8(u8 d)
32 p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
33 p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^
35 p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^
37 p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
38 p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^
39 GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
44 static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
50 for (i = 0; i < size; i++)
51 ecc[i] = calculate_parity_13_8(src[i]);
54 static u32 calc_chksum(void *buf, size_t size)
60 for (i = 0; i < size; i++)
66 static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
68 struct nand_chip *chip = mtd_to_nand(mtd);
69 struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
71 fcb->fingerprint = FCB_FINGERPRINT;
72 fcb->version = FCB_VERSION_1;
73 fcb->pagesize = mtd->writesize;
74 fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
75 fcb->sectors = mtd->erasesize / mtd->writesize;
77 /* Divide ECC strength by two and save the value into FCB structure. */
78 fcb->ecc_level = nand_info->bch_geometry.ecc_strength >> 1;
80 fcb->ecc_type = fcb->ecc_level;
82 /* Also hardcoded in kobs-ng */
83 fcb->ecc_nr = 0x00000200;
84 fcb->ecc_size = 0x00000200;
88 fcb->dsample_time = 6;
91 /* DBBT search area starts at second page on first block */
94 fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
95 fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
97 fcb->phy_offset = mtd->writesize;
99 fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
101 fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
104 static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
106 int n, n_bad_blocks = 0;
108 u32 *n_bad_blocksp = buf + 0x4;
110 for (n = 0; n < num_blocks; n++) {
111 loff_t offset = n * mtd->erasesize;
112 if (mtd_block_isbad(mtd, offset)) {
119 *n_bad_blocksp = n_bad_blocks;
124 static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
125 size_t maxsize, const u_char *buf)
127 nand_erase_options_t opts;
128 struct fcb_block *fcb;
129 struct dbbt_block *dbbt;
131 void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
132 int nr_blks, nr_blks_fcb, fw1_blk;
133 size_t fwsize, dummy;
137 memset(&opts, 0, sizeof(opts));
139 opts.length = maxsize - 1;
140 ret = nand_erase_opts(mtd, &opts);
142 printf("%s: erase failed (ret = %d)\n", __func__, ret);
147 * Reference documentation from i.MX6DQRM section 8.5.2.2
149 * Nand Boot Control Block(BCB) contains two data structures,
150 * - Firmware Configuration Block(FCB)
151 * - Discovered Bad Block Table(DBBT)
155 * - DBBT search page address,
156 * - start page address of primary firmware
157 * - start page address of secondary firmware
160 * - number of blocks = mtd partition size / mtd erasesize
161 * - two firmware blocks, primary and secondary
162 * - first 4 block for FCB/DBBT
163 * - rest split in half for primary and secondary firmware
164 * - same firmware will write two times
167 nr_blks = maxsize / mtd->erasesize;
168 fw1_blk = nr_blks_fcb;
171 fwsize = ALIGN(size + FLASH_OFFSET_STANDARD + mtd->writesize,
173 fwbuf = kzalloc(fwsize, GFP_KERNEL);
175 debug("failed to allocate fwbuf\n");
180 memcpy(fwbuf + FLASH_OFFSET_STANDARD, buf, size);
181 fw1_off = fw1_blk * mtd->erasesize;
182 ret = nand_write_skip_bad(mtd, fw1_off, &fwsize, NULL, maxsize,
183 (u_char *)fwbuf, WITH_WR_VERIFY);
184 printf("NAND fw write: 0x%llx offset, 0x%x bytes written: %s\n",
185 fw1_off, fwsize, ret ? "ERROR" : "OK");
190 fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
192 debug("failed to allocate fcb\n");
197 fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
198 fcb->fw1_pages = size / mtd->writesize + 1;
202 dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
204 debug("failed to allocate dbbt_page\n");
209 dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
210 if (!dbbt_data_page) {
211 debug("failed to allocate dbbt_data_page\n");
218 dbbt->fingerprint = DBBT_FINGERPRINT2;
219 dbbt->version = DBBT_VERSION_1;
220 ret = dbbt_fill_data(mtd, dbbt_data_page, nr_blks);
222 goto dbbt_data_page_err;
227 fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
229 debug("failed to allocate fcb_raw_page\n");
231 goto dbbt_data_page_err;
234 memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
235 encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
237 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
238 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
239 * the FCB is mostly written to the first page in a block, a scan for
240 * factory bad blocks will detect these blocks as bad, e.g. when
241 * function nand_scan_bbt() is executed to build a new bad block table.
243 memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
245 for (i = 0; i < nr_blks_fcb; i++) {
246 if (mtd_block_isbad(mtd, off)) {
247 printf("Block %d is bad, skipped\n", i);
252 mtd_oob_ops_t ops = {
253 .datbuf = (u8 *)fcb_raw_page,
254 .oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
255 .len = mtd->writesize,
256 .ooblen = mtd->oobsize,
260 ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
262 goto fcb_raw_page_err;
263 debug("NAND fcb write: 0x%x offset, 0x%x bytes written: %s\n",
264 mtd->erasesize * i, ops.len, ret ? "ERROR" : "OK");
266 ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
267 mtd->writesize, &dummy, dbbt_page);
269 goto fcb_raw_page_err;
270 debug("NAND dbbt write: 0x%x offset, 0x%x bytes written: %s\n",
271 mtd->erasesize * i + mtd->writesize, dummy,
272 ret ? "ERROR" : "OK");
274 /* dbbtpages == 0 if no bad blocks */
275 if (dbbt->dbbtpages > 0) {
276 loff_t to = (mtd->erasesize * i + mtd->writesize * 5);
278 ret = mtd_write(mtd, to, mtd->writesize, &dummy,
281 goto fcb_raw_page_err;
288 kfree(dbbt_data_page);
299 static int do_nandbcb_update(int argc, char * const argv[])
301 struct mtd_info *mtd;
302 loff_t addr, offset, size, maxsize;
309 return CMD_RET_USAGE;
311 dev = nand_curr_device;
313 printf("failed to get nand_curr_device, run nand device");
314 return CMD_RET_FAILURE;
317 addr = simple_strtoul(argv[1], &endp, 16);
318 if (*argv[1] == 0 || *endp != 0)
319 return CMD_RET_FAILURE;
321 mtd = get_nand_dev_by_index(dev);
322 if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &offset, &size,
323 &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
324 return CMD_RET_FAILURE;
326 buf = map_physmem(addr, size, MAP_WRBACK);
328 puts("failed to map physical memory\n");
329 return CMD_RET_FAILURE;
332 ret = nandbcb_update(mtd, offset, size, maxsize, buf);
334 return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
337 static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
350 if (strcmp(cmd, "update") == 0) {
351 ret = do_nandbcb_update(argc, argv);
359 return CMD_RET_USAGE;
362 #ifdef CONFIG_SYS_LONGHELP
363 static char nandbcb_help_text[] =
364 "update addr off|partition len - update 'len' bytes starting at\n"
365 " 'off|part' to memory address 'addr', skipping bad blocks";
368 U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,