cmd_nandbcb.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546
  1. /*
  2. * i.MX nand boot control block(bcb).
  3. *
  4. * Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
  5. *
  6. * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
  7. * Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
  8. *
  9. * Reconstucted by Han Xu <han.xu@nxp.com>
  10. *
  11. * SPDX-License-Identifier: GPL-2.0+
  12. */
  13. #include <common.h>
  14. #include <command.h>
  15. #include <log.h>
  16. #include <malloc.h>
  17. #include <nand.h>
  18. #include <dm/devres.h>
  19. #include <asm/io.h>
  20. #include <jffs2/jffs2.h>
  21. #include <linux/bch.h>
  22. #include <linux/mtd/mtd.h>
  23. #include <asm/arch/sys_proto.h>
  24. #include <asm/mach-imx/imx-nandbcb.h>
  25. #include <asm/mach-imx/imximage.cfg>
  26. #include <mxs_nand.h>
  27. #include <linux/mtd/mtd.h>
  28. #include <nand.h>
  29. #include <fuse.h>
  30. #include "../../../cmd/legacy-mtd-utils.h"
  31. /* FCB related flags */
  32. /* FCB layout with leading 12B reserved */
  33. #define FCB_LAYOUT_RESV_12B BIT(0)
  34. /* FCB layout with leading 32B meta data */
  35. #define FCB_LAYOUT_META_32B BIT(1)
  36. /* FCB encrypted by Hamming code */
  37. #define FCB_ENCODE_HAMMING BIT(2)
  38. /* FCB encrypted by 40bit BCH */
  39. #define FCB_ENCODE_BCH_40b BIT(3)
  40. /* FCB encrypted by 62bit BCH */
  41. #define FCB_ENCODE_BCH_62b BIT(4)
  42. /* FCB encrypted by BCH */
  43. #define FCB_ENCODE_BCH (FCB_ENCODE_BCH_40b | FCB_ENCODE_BCH_62b)
  44. /* FCB data was randomized */
  45. #define FCB_RANDON_ENABLED BIT(5)
  46. /* Firmware related flags */
  47. /* No 1K padding */
  48. #define FIRMWARE_NEED_PADDING BIT(8)
  49. /* Extra firmware*/
  50. #define FIRMWARE_EXTRA_ONE BIT(9)
  51. /* Secondary firmware on fixed address */
  52. #define FIRMWARE_SECONDARY_FIXED_ADDR BIT(10)
  53. /* Boot search related flags */
  54. #define BT_SEARCH_CNT_FROM_FUSE BIT(16)
  55. struct platform_config {
  56. int misc_flags;
  57. };
  58. static struct platform_config plat_config;
  59. /* imx6q/dl/solo */
  60. static struct platform_config imx6qdl_plat_config = {
  61. .misc_flags = FCB_LAYOUT_RESV_12B |
  62. FCB_ENCODE_HAMMING |
  63. FIRMWARE_NEED_PADDING,
  64. };
  65. static struct platform_config imx6sx_plat_config = {
  66. .misc_flags = FCB_LAYOUT_META_32B |
  67. FCB_ENCODE_BCH_62b |
  68. FIRMWARE_NEED_PADDING |
  69. FCB_RANDON_ENABLED,
  70. };
  71. static struct platform_config imx7d_plat_config = {
  72. .misc_flags = FCB_LAYOUT_META_32B |
  73. FCB_ENCODE_BCH_62b |
  74. FIRMWARE_NEED_PADDING |
  75. FCB_RANDON_ENABLED,
  76. };
  77. /* imx6ul/ull/ulz */
  78. static struct platform_config imx6ul_plat_config = {
  79. .misc_flags = FCB_LAYOUT_META_32B |
  80. FCB_ENCODE_BCH_40b |
  81. FIRMWARE_NEED_PADDING,
  82. };
  83. static struct platform_config imx8mq_plat_config = {
  84. .misc_flags = FCB_LAYOUT_META_32B |
  85. FCB_ENCODE_BCH_62b |
  86. FIRMWARE_NEED_PADDING |
  87. FCB_RANDON_ENABLED |
  88. FIRMWARE_EXTRA_ONE,
  89. };
  90. /* all other imx8mm */
  91. static struct platform_config imx8mm_plat_config = {
  92. .misc_flags = FCB_LAYOUT_META_32B |
  93. FCB_ENCODE_BCH_62b |
  94. FIRMWARE_NEED_PADDING |
  95. FCB_RANDON_ENABLED,
  96. };
  97. /* imx8mn */
  98. static struct platform_config imx8mn_plat_config = {
  99. .misc_flags = FCB_LAYOUT_META_32B |
  100. FCB_ENCODE_BCH_62b |
  101. FCB_RANDON_ENABLED |
  102. FIRMWARE_SECONDARY_FIXED_ADDR |
  103. BT_SEARCH_CNT_FROM_FUSE,
  104. };
  105. /* imx8qx/qm */
  106. static struct platform_config imx8q_plat_config = {
  107. .misc_flags = FCB_LAYOUT_META_32B |
  108. FCB_ENCODE_BCH_62b |
  109. FCB_RANDON_ENABLED |
  110. FIRMWARE_SECONDARY_FIXED_ADDR |
  111. BT_SEARCH_CNT_FROM_FUSE,
  112. };
  113. /* boot search related variables and definitions */
  114. static int g_boot_search_count = 4;
  115. static int g_boot_search_stride;
  116. static int g_pages_per_stride;
  117. /* mtd config structure */
  118. struct boot_config {
  119. int dev;
  120. struct mtd_info *mtd;
  121. loff_t maxsize;
  122. loff_t input_size;
  123. loff_t offset;
  124. loff_t boot_stream1_address;
  125. loff_t boot_stream2_address;
  126. size_t boot_stream1_size;
  127. size_t boot_stream2_size;
  128. size_t max_boot_stream_size;
  129. int stride_size_in_byte;
  130. int search_area_size_in_bytes;
  131. int search_area_size_in_pages;
  132. int secondary_boot_stream_off_in_MB;
  133. };
  134. /* boot_stream config structure */
  135. struct boot_stream_config {
  136. char bs_label[32];
  137. loff_t bs_addr;
  138. size_t bs_size;
  139. void *bs_buf;
  140. loff_t next_bs_addr;
  141. bool need_padding;
  142. };
  143. /* FW index */
  144. #define FW1_ONLY 1
  145. #define FW2_ONLY 2
  146. #define FW_ALL FW1_ONLY | FW2_ONLY
  147. #define FW_INX(x) (1 << (x))
  148. /* NAND convert macros */
  149. #define CONV_TO_PAGES(x) ((u32)(x) / (u32)(mtd->writesize))
  150. #define CONV_TO_BLOCKS(x) ((u32)(x) / (u32)(mtd->erasesize))
  151. #define GETBIT(v, n) (((v) >> (n)) & 0x1)
  152. #define IMX8MQ_SPL_SZ 0x3e000
  153. #define IMX8MQ_HDMI_FW_SZ 0x19c00
  154. static int nandbcb_get_info(int argc, char * const argv[],
  155. struct boot_config *boot_cfg)
  156. {
  157. int dev;
  158. struct mtd_info *mtd;
  159. dev = nand_curr_device;
  160. if (dev < 0) {
  161. printf("failed to get nand_curr_device, run nand device\n");
  162. return CMD_RET_FAILURE;
  163. }
  164. mtd = get_nand_dev_by_index(dev);
  165. if (!mtd) {
  166. printf("failed to get mtd info\n");
  167. return CMD_RET_FAILURE;
  168. }
  169. boot_cfg->dev = dev;
  170. boot_cfg->mtd = mtd;
  171. return CMD_RET_SUCCESS;
  172. }
  173. static int nandbcb_get_size(int argc, char * const argv[], int num,
  174. struct boot_config *boot_cfg)
  175. {
  176. int dev;
  177. loff_t offset, size, maxsize;
  178. struct mtd_info *mtd;
  179. dev = boot_cfg->dev;
  180. mtd = boot_cfg->mtd;
  181. size = 0;
  182. if (mtd_arg_off_size(argc - num, argv + num, &dev, &offset, &size,
  183. &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
  184. return CMD_RET_FAILURE;
  185. boot_cfg->maxsize = maxsize;
  186. boot_cfg->offset = offset;
  187. debug("max: %llx, offset: %llx\n", maxsize, offset);
  188. if (size && size != maxsize)
  189. boot_cfg->input_size = size;
  190. return CMD_RET_SUCCESS;
  191. }
  192. static int nandbcb_set_boot_config(int argc, char * const argv[],
  193. struct boot_config *boot_cfg)
  194. {
  195. struct mtd_info *mtd;
  196. loff_t maxsize;
  197. loff_t boot_stream1_address, boot_stream2_address, max_boot_stream_size;
  198. if (!boot_cfg->mtd) {
  199. printf("Didn't get the mtd info, quit\n");
  200. return CMD_RET_FAILURE;
  201. }
  202. mtd = boot_cfg->mtd;
  203. /*
  204. * By default
  205. * set the search count as 4
  206. * set each FCB/DBBT/Firmware offset at the beginning of blocks
  207. * customers may change the value as needed
  208. */
  209. /* if need more compact layout, change these values */
  210. /* g_boot_search_count was set as 4 at the definition*/
  211. /* g_pages_per_stride was set as block size */
  212. g_pages_per_stride = mtd->erasesize / mtd->writesize;
  213. g_boot_search_stride = mtd->writesize * g_pages_per_stride;
  214. boot_cfg->stride_size_in_byte = g_boot_search_stride * mtd->writesize;
  215. boot_cfg->search_area_size_in_bytes =
  216. g_boot_search_count * g_boot_search_stride;
  217. boot_cfg->search_area_size_in_pages =
  218. boot_cfg->search_area_size_in_bytes / mtd->writesize;
  219. /* after FCB/DBBT, split the rest of area for two Firmwares */
  220. if (!boot_cfg->maxsize) {
  221. printf("Didn't get the maxsize, quit\n");
  222. return CMD_RET_FAILURE;
  223. }
  224. maxsize = boot_cfg->maxsize;
  225. /* align to page boundary */
  226. maxsize = ((u32)(maxsize + mtd->writesize - 1)) / (u32)mtd->writesize
  227. * mtd->writesize;
  228. boot_stream1_address = 2 * boot_cfg->search_area_size_in_bytes;
  229. boot_stream2_address = ((maxsize - boot_stream1_address) / 2 +
  230. boot_stream1_address);
  231. if (boot_cfg->secondary_boot_stream_off_in_MB)
  232. boot_stream2_address = boot_cfg->secondary_boot_stream_off_in_MB * 1024 * 1024;
  233. max_boot_stream_size = boot_stream2_address - boot_stream1_address;
  234. /* sanity check */
  235. if (max_boot_stream_size <= 0) {
  236. debug("st1_addr: %llx, st2_addr: %llx, max: %llx\n",
  237. boot_stream1_address, boot_stream2_address,
  238. max_boot_stream_size);
  239. printf("something wrong with firmware address settings\n");
  240. return CMD_RET_FAILURE;
  241. }
  242. boot_cfg->boot_stream1_address = boot_stream1_address;
  243. boot_cfg->boot_stream2_address = boot_stream2_address;
  244. boot_cfg->max_boot_stream_size = max_boot_stream_size;
  245. /* set the boot_stream size as the input size now */
  246. if (boot_cfg->input_size) {
  247. boot_cfg->boot_stream1_size = boot_cfg->input_size;
  248. boot_cfg->boot_stream2_size = boot_cfg->input_size;
  249. }
  250. return CMD_RET_SUCCESS;
  251. }
  252. static int nandbcb_check_space(struct boot_config *boot_cfg)
  253. {
  254. size_t maxsize = boot_cfg->maxsize;
  255. size_t max_boot_stream_size = boot_cfg->max_boot_stream_size;
  256. loff_t boot_stream2_address = boot_cfg->boot_stream2_address;
  257. if (boot_cfg->boot_stream1_size &&
  258. boot_cfg->boot_stream1_size > max_boot_stream_size) {
  259. printf("boot stream1 doesn't fit, check partition size or settings\n");
  260. return CMD_RET_FAILURE;
  261. }
  262. if (boot_cfg->boot_stream2_size &&
  263. boot_cfg->boot_stream2_size > maxsize - boot_stream2_address) {
  264. printf("boot stream2 doesn't fit, check partition size or settings\n");
  265. return CMD_RET_FAILURE;
  266. }
  267. return CMD_RET_SUCCESS;
  268. }
  269. #if defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL)
  270. static uint8_t reverse_bit(uint8_t b)
  271. {
  272. b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
  273. b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
  274. b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
  275. return b;
  276. }
  277. static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits)
  278. {
  279. int i, j, m = 13;
  280. int blocksize = 128;
  281. int numblocks = 8;
  282. int ecc_buf_size = (m * eccbits + 7) / 8;
  283. struct bch_control *bch = init_bch(m, eccbits, 0);
  284. u8 *ecc_buf = kzalloc(ecc_buf_size, GFP_KERNEL);
  285. u8 *tmp_buf = kzalloc(blocksize * numblocks, GFP_KERNEL);
  286. u8 *psrc, *pdst;
  287. /*
  288. * The blocks here are bit aligned. If eccbits is a multiple of 8,
  289. * we just can copy bytes. Otherwiese we must move the blocks to
  290. * the next free bit position.
  291. */
  292. WARN_ON(eccbits % 8);
  293. memcpy(tmp_buf, fcb, sizeof(*fcb));
  294. for (i = 0; i < numblocks; i++) {
  295. memset(ecc_buf, 0, ecc_buf_size);
  296. psrc = tmp_buf + i * blocksize;
  297. pdst = buf + i * (blocksize + ecc_buf_size);
  298. /* copy data byte aligned to destination buf */
  299. memcpy(pdst, psrc, blocksize);
  300. /*
  301. * imx-kobs use a modified encode_bch which reverse the
  302. * bit order of the data before calculating bch.
  303. * Do this in the buffer and use the bch lib here.
  304. */
  305. for (j = 0; j < blocksize; j++)
  306. psrc[j] = reverse_bit(psrc[j]);
  307. encode_bch(bch, psrc, blocksize, ecc_buf);
  308. /* reverse ecc bit */
  309. for (j = 0; j < ecc_buf_size; j++)
  310. ecc_buf[j] = reverse_bit(ecc_buf[j]);
  311. /* Here eccbuf is byte aligned and we can just copy it */
  312. memcpy(pdst + blocksize, ecc_buf, ecc_buf_size);
  313. }
  314. kfree(ecc_buf);
  315. kfree(tmp_buf);
  316. free_bch(bch);
  317. }
  318. #else
  319. static u8 calculate_parity_13_8(u8 d)
  320. {
  321. u8 p = 0;
  322. p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
  323. p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^
  324. GETBIT(d, 1)) << 1;
  325. p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^
  326. GETBIT(d, 0)) << 2;
  327. p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
  328. p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^
  329. GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
  330. return p;
  331. }
  332. static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
  333. {
  334. int i;
  335. u8 *src = _src;
  336. u8 *ecc = _ecc;
  337. for (i = 0; i < size; i++)
  338. ecc[i] = calculate_parity_13_8(src[i]);
  339. }
  340. #endif
  341. static u32 calc_chksum(void *buf, size_t size)
  342. {
  343. u32 chksum = 0;
  344. u8 *bp = buf;
  345. size_t i;
  346. for (i = 0; i < size; i++)
  347. chksum += bp[i];
  348. return ~chksum;
  349. }
  350. static void fill_fcb(struct fcb_block *fcb, struct boot_config *boot_cfg)
  351. {
  352. struct mtd_info *mtd = boot_cfg->mtd;
  353. struct nand_chip *chip = mtd_to_nand(mtd);
  354. struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
  355. struct mxs_nand_layout l;
  356. mxs_nand_get_layout(mtd, &l);
  357. fcb->fingerprint = FCB_FINGERPRINT;
  358. fcb->version = FCB_VERSION_1;
  359. fcb->datasetup = 80;
  360. fcb->datahold = 60;
  361. fcb->addr_setup = 25;
  362. fcb->dsample_time = 6;
  363. fcb->pagesize = mtd->writesize;
  364. fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
  365. fcb->sectors = mtd->erasesize / mtd->writesize;
  366. fcb->meta_size = l.meta_size;
  367. fcb->nr_blocks = l.nblocks;
  368. fcb->ecc_nr = l.data0_size;
  369. fcb->ecc_level = l.ecc0;
  370. fcb->ecc_size = l.datan_size;
  371. fcb->ecc_type = l.eccn;
  372. fcb->bchtype = l.gf_len;
  373. /* DBBT search area starts from the next block after all FCB */
  374. fcb->dbbt_start = boot_cfg->search_area_size_in_pages;
  375. fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
  376. fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
  377. fcb->phy_offset = mtd->writesize;
  378. fcb->disbbm = 0;
  379. fcb->fw1_start = CONV_TO_PAGES(boot_cfg->boot_stream1_address);
  380. fcb->fw2_start = CONV_TO_PAGES(boot_cfg->boot_stream2_address);
  381. fcb->fw1_pages = CONV_TO_PAGES(boot_cfg->boot_stream1_size);
  382. fcb->fw2_pages = CONV_TO_PAGES(boot_cfg->boot_stream2_size);
  383. fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
  384. }
  385. static int fill_dbbt_data(struct mtd_info *mtd, void *buf, int num_blocks)
  386. {
  387. int n, n_bad_blocks = 0;
  388. u32 *bb = buf + 0x8;
  389. u32 *n_bad_blocksp = buf + 0x4;
  390. for (n = 0; n < num_blocks; n++) {
  391. loff_t offset = n * mtd->erasesize;
  392. if (mtd_block_isbad(mtd, offset)) {
  393. n_bad_blocks++;
  394. *bb = n;
  395. bb++;
  396. }
  397. }
  398. *n_bad_blocksp = n_bad_blocks;
  399. return n_bad_blocks;
  400. }
  401. /*
  402. * return 1 - bad block
  403. * return 0 - read successfully
  404. * return < 0 - read failed
  405. */
  406. static int read_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb,
  407. loff_t off)
  408. {
  409. struct mtd_info *mtd;
  410. void *fcb_raw_page;
  411. size_t size;
  412. int ret = 0;
  413. mtd = boot_cfg->mtd;
  414. fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
  415. if (mtd_block_isbad(mtd, off)) {
  416. printf("Block %d is bad, skipped\n", (int)CONV_TO_BLOCKS(off));
  417. return 1;
  418. }
  419. /*
  420. * User BCH hardware to decode ECC for FCB
  421. */
  422. if (plat_config.misc_flags & FCB_ENCODE_BCH) {
  423. size = sizeof(struct fcb_block);
  424. /* switch nand BCH to FCB compatible settings */
  425. if (plat_config.misc_flags & FCB_ENCODE_BCH_62b)
  426. mxs_nand_mode_fcb_62bit(mtd);
  427. else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
  428. mxs_nand_mode_fcb_40bit(mtd);
  429. ret = nand_read(mtd, off, &size, (u_char *)fcb);
  430. /* switch BCH back */
  431. mxs_nand_mode_normal(mtd);
  432. printf("NAND FCB read from 0x%llx offset 0x%zx read: %s\n",
  433. off, size, ret ? "ERROR" : "OK");
  434. } else if (plat_config.misc_flags & FCB_ENCODE_HAMMING) {
  435. /* raw read*/
  436. mtd_oob_ops_t ops = {
  437. .datbuf = (u8 *)fcb_raw_page,
  438. .oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
  439. .len = mtd->writesize,
  440. .ooblen = mtd->oobsize,
  441. .mode = MTD_OPS_RAW
  442. };
  443. ret = mtd_read_oob(mtd, off, &ops);
  444. printf("NAND FCB read from 0x%llx offset 0x%zx read: %s\n",
  445. off, ops.len, ret ? "ERROR" : "OK");
  446. }
  447. if (ret)
  448. goto fcb_raw_page_err;
  449. if ((plat_config.misc_flags & FCB_ENCODE_HAMMING) &&
  450. (plat_config.misc_flags & FCB_LAYOUT_RESV_12B))
  451. memcpy(fcb, fcb_raw_page + 12, sizeof(struct fcb_block));
  452. /* TODO: check if it can pass Hamming check */
  453. fcb_raw_page_err:
  454. kfree(fcb_raw_page);
  455. return ret;
  456. }
  457. static int write_fcb(struct boot_config *boot_cfg, struct fcb_block *fcb)
  458. {
  459. struct mtd_info *mtd;
  460. void *fcb_raw_page = NULL;
  461. int i, ret;
  462. loff_t off;
  463. size_t size;
  464. mtd = boot_cfg->mtd;
  465. /*
  466. * We prepare raw page only for i.MX6, for i.MX7 we
  467. * leverage BCH hw module instead
  468. */
  469. if ((plat_config.misc_flags & FCB_ENCODE_HAMMING) &&
  470. (plat_config.misc_flags & FCB_LAYOUT_RESV_12B)) {
  471. fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
  472. GFP_KERNEL);
  473. if (!fcb_raw_page) {
  474. debug("failed to allocate fcb_raw_page\n");
  475. ret = -ENOMEM;
  476. return ret;
  477. }
  478. #if defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL)
  479. /* 40 bit BCH, for i.MX6UL(L) */
  480. encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
  481. #else
  482. memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
  483. encode_hamming_13_8(fcb_raw_page + 12,
  484. fcb_raw_page + 12 + 512, 512);
  485. #endif
  486. /*
  487. * Set the first and second byte of OOB data to 0xFF,
  488. * not 0x00. These bytes are used as the Manufacturers Bad
  489. * Block Marker (MBBM). Since the FCB is mostly written to
  490. * the first page in a block, a scan for
  491. * factory bad blocks will detect these blocks as bad, e.g.
  492. * when function nand_scan_bbt() is executed to build a new
  493. * bad block table.
  494. */
  495. memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
  496. }
  497. /* start writing FCB from the very beginning */
  498. off = 0;
  499. for (i = 0; i < g_boot_search_count; i++) {
  500. if (mtd_block_isbad(mtd, off)) {
  501. printf("Block %d is bad, skipped\n", i);
  502. continue;
  503. }
  504. /*
  505. * User BCH hardware module to generate ECC for FCB
  506. */
  507. if (plat_config.misc_flags & FCB_ENCODE_BCH) {
  508. size = sizeof(struct fcb_block);
  509. /* switch nand BCH to FCB compatible settings */
  510. if (plat_config.misc_flags & FCB_ENCODE_BCH_62b)
  511. mxs_nand_mode_fcb_62bit(mtd);
  512. else if (plat_config.misc_flags & FCB_ENCODE_BCH_40b)
  513. mxs_nand_mode_fcb_40bit(mtd);
  514. ret = nand_write(mtd, off, &size, (u_char *)fcb);
  515. /* switch BCH back */
  516. mxs_nand_mode_normal(mtd);
  517. printf("NAND FCB write to 0x%zx offset 0x%llx written: %s\n",
  518. size, off, ret ? "ERROR" : "OK");
  519. } else if (plat_config.misc_flags & FCB_ENCODE_HAMMING) {
  520. /* raw write */
  521. mtd_oob_ops_t ops = {
  522. .datbuf = (u8 *)fcb_raw_page,
  523. .oobbuf = ((u8 *)fcb_raw_page) +
  524. mtd->writesize,
  525. .len = mtd->writesize,
  526. .ooblen = mtd->oobsize,
  527. .mode = MTD_OPS_RAW
  528. };
  529. ret = mtd_write_oob(mtd, off, &ops);
  530. printf("NAND FCB write to 0x%llxx offset 0x%zx written: %s\n", off, ops.len, ret ? "ERROR" : "OK");
  531. }
  532. if (ret)
  533. goto fcb_raw_page_err;
  534. /* next writing location */
  535. off += g_boot_search_stride;
  536. }
  537. return 0;
  538. fcb_raw_page_err:
  539. kfree(fcb_raw_page);
  540. return ret;
  541. }
  542. /*
  543. * return 1 - bad block
  544. * return 0 - read successfully
  545. * return < 0 - read failed
  546. */
  547. static int read_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
  548. void *dbbt_data_page, loff_t off)
  549. {
  550. size_t size;
  551. struct mtd_info *mtd;
  552. loff_t to;
  553. int ret;
  554. mtd = boot_cfg->mtd;
  555. if (mtd_block_isbad(mtd, off)) {
  556. printf("Block %d is bad, skipped\n",
  557. (int)CONV_TO_BLOCKS(off));
  558. return 1;
  559. }
  560. size = sizeof(struct dbbt_block);
  561. ret = nand_read(mtd, off, &size, (u_char *)dbbt);
  562. printf("NAND DBBT read from 0x%llx offset 0x%zx read: %s\n",
  563. off, size, ret ? "ERROR" : "OK");
  564. if (ret)
  565. return ret;
  566. /* dbbtpages == 0 if no bad blocks */
  567. if (dbbt->dbbtpages > 0) {
  568. to = off + 4 * mtd->writesize;
  569. size = mtd->writesize;
  570. ret = nand_read(mtd, to, &size, dbbt_data_page);
  571. printf("DBBT data read from 0x%llx offset 0x%zx read: %s\n",
  572. to, size, ret ? "ERROR" : "OK");
  573. if (ret)
  574. return ret;
  575. }
  576. return 0;
  577. }
  578. static int write_dbbt(struct boot_config *boot_cfg, struct dbbt_block *dbbt,
  579. void *dbbt_data_page)
  580. {
  581. int i;
  582. loff_t off, to;
  583. size_t size;
  584. struct mtd_info *mtd;
  585. int ret;
  586. mtd = boot_cfg->mtd;
  587. /* start writing DBBT after all FCBs */
  588. off = boot_cfg->search_area_size_in_bytes;
  589. size = mtd->writesize;
  590. for (i = 0; i < g_boot_search_count; i++) {
  591. if (mtd_block_isbad(mtd, off)) {
  592. printf("Block %d is bad, skipped\n",
  593. (int)(i + CONV_TO_BLOCKS(off)));
  594. continue;
  595. }
  596. ret = nand_write(mtd, off, &size, (u_char *)dbbt);
  597. printf("NAND DBBT write to 0x%llx offset 0x%zx written: %s\n",
  598. off, size, ret ? "ERROR" : "OK");
  599. if (ret)
  600. return ret;
  601. /* dbbtpages == 0 if no bad blocks */
  602. if (dbbt->dbbtpages > 0) {
  603. to = off + 4 * mtd->writesize;
  604. ret = nand_write(mtd, to, &size, dbbt_data_page);
  605. printf("DBBT data write to 0x%llx offset 0x%zx written: %s\n",
  606. to, size, ret ? "ERROR" : "OK");
  607. if (ret)
  608. return ret;
  609. }
  610. /* next writing location */
  611. off += g_boot_search_stride;
  612. }
  613. return 0;
  614. }
  615. /* reuse the check_skip_len from nand_util.c with minor change*/
  616. static int check_skip_length(struct boot_config *boot_cfg, loff_t offset,
  617. size_t length, size_t *used)
  618. {
  619. struct mtd_info *mtd = boot_cfg->mtd;
  620. size_t maxsize = boot_cfg->maxsize;
  621. size_t len_excl_bad = 0;
  622. int ret = 0;
  623. while (len_excl_bad < length) {
  624. size_t block_len, block_off;
  625. loff_t block_start;
  626. if (offset >= maxsize)
  627. return -1;
  628. block_start = offset & ~(loff_t)(mtd->erasesize - 1);
  629. block_off = offset & (mtd->erasesize - 1);
  630. block_len = mtd->erasesize - block_off;
  631. if (!nand_block_isbad(mtd, block_start))
  632. len_excl_bad += block_len;
  633. else
  634. ret = 1;
  635. offset += block_len;
  636. *used += block_len;
  637. }
  638. /* If the length is not a multiple of block_len, adjust. */
  639. if (len_excl_bad > length)
  640. *used -= (len_excl_bad - length);
  641. return ret;
  642. }
  643. static int nandbcb_get_next_good_blk_addr(struct boot_config *boot_cfg,
  644. struct boot_stream_config *bs_cfg)
  645. {
  646. struct mtd_info *mtd = boot_cfg->mtd;
  647. loff_t offset = bs_cfg->bs_addr;
  648. size_t length = bs_cfg->bs_size;
  649. size_t used = 0;
  650. int ret;
  651. ret = check_skip_length(boot_cfg, offset, length, &used);
  652. if (ret < 0)
  653. return ret;
  654. /* get next image address */
  655. bs_cfg->next_bs_addr = (u32)(offset + used + mtd->erasesize - 1)
  656. / (u32)mtd->erasesize * mtd->erasesize;
  657. return ret;
  658. }
  659. static int nandbcb_write_bs_skip_bad(struct boot_config *boot_cfg,
  660. struct boot_stream_config *bs_cfg)
  661. {
  662. struct mtd_info *mtd;
  663. void *buf;
  664. loff_t offset, maxsize;
  665. size_t size;
  666. size_t length;
  667. int ret;
  668. bool padding_flag = false;
  669. mtd = boot_cfg->mtd;
  670. offset = bs_cfg->bs_addr;
  671. maxsize = boot_cfg->maxsize;
  672. size = bs_cfg->bs_size;
  673. /* some boot images may need leading offset */
  674. if (bs_cfg->need_padding &&
  675. (plat_config.misc_flags & FIRMWARE_NEED_PADDING))
  676. padding_flag = 1;
  677. if (padding_flag)
  678. length = ALIGN(size + FLASH_OFFSET_STANDARD, mtd->writesize);
  679. else
  680. length = ALIGN(size, mtd->writesize);
  681. buf = kzalloc(length, GFP_KERNEL);
  682. if (!buf) {
  683. printf("failed to allocate buffer for firmware\n");
  684. ret = -ENOMEM;
  685. return ret;
  686. }
  687. if (padding_flag)
  688. memcpy(buf + FLASH_OFFSET_STANDARD, bs_cfg->bs_buf, size);
  689. else
  690. memcpy(buf, bs_cfg->bs_buf, size);
  691. ret = nand_write_skip_bad(mtd, offset, &length, NULL, maxsize,
  692. (u_char *)buf, WITH_WR_VERIFY);
  693. printf("Write %s @0x%llx offset, 0x%zx bytes written: %s\n",
  694. bs_cfg->bs_label, offset, length, ret ? "ERROR" : "OK");
  695. if (ret)
  696. /* write image failed, quit */
  697. goto err;
  698. /* get next good blk address if needed */
  699. if (bs_cfg->need_padding) {
  700. ret = nandbcb_get_next_good_blk_addr(boot_cfg, bs_cfg);
  701. if (ret < 0) {
  702. printf("Next image cannot fit in NAND partition\n");
  703. goto err;
  704. }
  705. }
  706. /* now we know how the exact image size written to NAND */
  707. bs_cfg->bs_size = length;
  708. return 0;
  709. err:
  710. kfree(buf);
  711. return ret;
  712. }
  713. static int nandbcb_write_fw(struct boot_config *boot_cfg, u_char *buf,
  714. int index)
  715. {
  716. int i;
  717. loff_t offset;
  718. size_t size;
  719. loff_t next_bs_addr;
  720. struct boot_stream_config bs_cfg;
  721. int ret;
  722. for (i = 0; i < 2; ++i) {
  723. if (!(FW_INX(i) & index))
  724. continue;
  725. if (i == 0) {
  726. offset = boot_cfg->boot_stream1_address;
  727. size = boot_cfg->boot_stream1_size;
  728. } else {
  729. offset = boot_cfg->boot_stream2_address;
  730. size = boot_cfg->boot_stream2_size;
  731. }
  732. /* write Firmware*/
  733. if (!(plat_config.misc_flags & FIRMWARE_EXTRA_ONE)) {
  734. memset(&bs_cfg, 0, sizeof(struct boot_stream_config));
  735. sprintf(bs_cfg.bs_label, "firmware%d", i);
  736. bs_cfg.bs_addr = offset;
  737. bs_cfg.bs_size = size;
  738. bs_cfg.bs_buf = buf;
  739. bs_cfg.need_padding = 1;
  740. ret = nandbcb_write_bs_skip_bad(boot_cfg, &bs_cfg);
  741. if (ret)
  742. return ret;
  743. /* update the boot stream size */
  744. if (i == 0)
  745. boot_cfg->boot_stream1_size = bs_cfg.bs_size;
  746. else
  747. boot_cfg->boot_stream2_size = bs_cfg.bs_size;
  748. } else {
  749. /* some platforms need extra firmware */
  750. memset(&bs_cfg, 0, sizeof(struct boot_stream_config));
  751. sprintf(bs_cfg.bs_label, "fw%d_part%d", i, 1);
  752. bs_cfg.bs_addr = offset;
  753. bs_cfg.bs_size = IMX8MQ_HDMI_FW_SZ;
  754. bs_cfg.bs_buf = buf;
  755. bs_cfg.need_padding = 1;
  756. ret = nandbcb_write_bs_skip_bad(boot_cfg, &bs_cfg);
  757. if (ret)
  758. return ret;
  759. /* update the boot stream size */
  760. if (i == 0)
  761. boot_cfg->boot_stream1_size = bs_cfg.bs_size;
  762. else
  763. boot_cfg->boot_stream2_size = bs_cfg.bs_size;
  764. /* get next image address */
  765. next_bs_addr = bs_cfg.next_bs_addr;
  766. memset(&bs_cfg, 0, sizeof(struct boot_stream_config));
  767. sprintf(bs_cfg.bs_label, "fw%d_part%d", i, 2);
  768. bs_cfg.bs_addr = next_bs_addr;
  769. bs_cfg.bs_size = IMX8MQ_SPL_SZ;
  770. bs_cfg.bs_buf = (u_char *)(buf + IMX8MQ_HDMI_FW_SZ);
  771. bs_cfg.need_padding = 0;
  772. ret = nandbcb_write_bs_skip_bad(boot_cfg, &bs_cfg);
  773. if (ret)
  774. return ret;
  775. }
  776. }
  777. return 0;
  778. }
  779. static int nandbcb_init(struct boot_config *boot_cfg, u_char *buf)
  780. {
  781. struct mtd_info *mtd;
  782. nand_erase_options_t opts;
  783. struct fcb_block *fcb;
  784. struct dbbt_block *dbbt;
  785. void *dbbt_page, *dbbt_data_page;
  786. int ret;
  787. loff_t maxsize, off;
  788. mtd = boot_cfg->mtd;
  789. maxsize = boot_cfg->maxsize;
  790. off = boot_cfg->offset;
  791. /* erase */
  792. memset(&opts, 0, sizeof(opts));
  793. opts.offset = off;
  794. opts.length = maxsize - 1;
  795. ret = nand_erase_opts(mtd, &opts);
  796. if (ret) {
  797. printf("%s: erase failed (ret = %d)\n", __func__, ret);
  798. return ret;
  799. }
  800. /*
  801. * Reference documentation from i.MX6DQRM section 8.5.2.2
  802. *
  803. * Nand Boot Control Block(BCB) contains two data structures,
  804. * - Firmware Configuration Block(FCB)
  805. * - Discovered Bad Block Table(DBBT)
  806. *
  807. * FCB contains,
  808. * - nand timings
  809. * - DBBT search page address,
  810. * - start page address of primary firmware
  811. * - start page address of secondary firmware
  812. *
  813. * setup fcb:
  814. * - number of blocks = mtd partition size / mtd erasesize
  815. * - two firmware blocks, primary and secondary
  816. * - first 4 block for FCB/DBBT
  817. * - rest split in half for primary and secondary firmware
  818. * - same firmware write twice
  819. */
  820. /* write Firmware*/
  821. ret = nandbcb_write_fw(boot_cfg, buf, FW_ALL);
  822. if (ret)
  823. goto err;
  824. /* fill fcb */
  825. fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
  826. if (!fcb) {
  827. debug("failed to allocate fcb\n");
  828. ret = -ENOMEM;
  829. return ret;
  830. }
  831. fill_fcb(fcb, boot_cfg);
  832. ret = write_fcb(boot_cfg, fcb);
  833. /* fill dbbt */
  834. dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
  835. if (!dbbt_page) {
  836. debug("failed to allocate dbbt_page\n");
  837. ret = -ENOMEM;
  838. goto fcb_err;
  839. }
  840. dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
  841. if (!dbbt_data_page) {
  842. debug("failed to allocate dbbt_data_page\n");
  843. ret = -ENOMEM;
  844. goto dbbt_page_err;
  845. }
  846. dbbt = dbbt_page;
  847. dbbt->checksum = 0;
  848. dbbt->fingerprint = DBBT_FINGERPRINT;
  849. dbbt->version = DBBT_VERSION_1;
  850. ret = fill_dbbt_data(mtd, dbbt_data_page, CONV_TO_BLOCKS(maxsize));
  851. if (ret < 0)
  852. goto dbbt_data_page_err;
  853. else if (ret > 0)
  854. dbbt->dbbtpages = 1;
  855. /* write dbbt */
  856. ret = write_dbbt(boot_cfg, dbbt, dbbt_data_page);
  857. if (ret < 0)
  858. printf("failed to write FCB/DBBT\n");
  859. dbbt_data_page_err:
  860. kfree(dbbt_data_page);
  861. dbbt_page_err:
  862. kfree(dbbt_page);
  863. fcb_err:
  864. kfree(fcb);
  865. err:
  866. return ret;
  867. }
  868. static int do_nandbcb_bcbonly(int argc, char *const argv[])
  869. {
  870. struct fcb_block *fcb;
  871. struct dbbt_block *dbbt;
  872. struct mtd_info *mtd;
  873. nand_erase_options_t opts;
  874. size_t maxsize;
  875. loff_t off;
  876. void *dbbt_page, *dbbt_data_page;
  877. int ret;
  878. struct boot_config cfg;
  879. if (argc < 4)
  880. return CMD_RET_USAGE;
  881. memset(&cfg, 0, sizeof(struct boot_config));
  882. if (nandbcb_get_info(argc, argv, &cfg))
  883. return CMD_RET_FAILURE;
  884. /* only get the partition info */
  885. if (nandbcb_get_size(2, argv, 1, &cfg))
  886. return CMD_RET_FAILURE;
  887. if (nandbcb_set_boot_config(argc, argv, &cfg))
  888. return CMD_RET_FAILURE;
  889. mtd = cfg.mtd;
  890. cfg.boot_stream1_address = simple_strtoul(argv[2], NULL, 16);
  891. cfg.boot_stream1_size = simple_strtoul(argv[3], NULL, 16);
  892. cfg.boot_stream1_size = ALIGN(cfg.boot_stream1_size, mtd->writesize);
  893. if (argc > 5) {
  894. cfg.boot_stream2_address = simple_strtoul(argv[4], NULL, 16);
  895. cfg.boot_stream2_size = simple_strtoul(argv[5], NULL, 16);
  896. cfg.boot_stream2_size = ALIGN(cfg.boot_stream2_size,
  897. mtd->writesize);
  898. }
  899. /* sanity check */
  900. nandbcb_check_space(&cfg);
  901. maxsize = cfg.maxsize;
  902. off = cfg.offset;
  903. /* erase the previous FCB/DBBT */
  904. memset(&opts, 0, sizeof(opts));
  905. opts.offset = off;
  906. opts.length = g_boot_search_stride * 2;
  907. ret = nand_erase_opts(mtd, &opts);
  908. if (ret) {
  909. printf("%s: erase failed (ret = %d)\n", __func__, ret);
  910. return CMD_RET_FAILURE;
  911. }
  912. /* fill fcb */
  913. fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
  914. if (!fcb) {
  915. printf("failed to allocate fcb\n");
  916. ret = -ENOMEM;
  917. return CMD_RET_FAILURE;
  918. }
  919. fill_fcb(fcb, &cfg);
  920. /* write fcb */
  921. ret = write_fcb(&cfg, fcb);
  922. /* fill dbbt */
  923. dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
  924. if (!dbbt_page) {
  925. printf("failed to allocate dbbt_page\n");
  926. ret = -ENOMEM;
  927. goto fcb_err;
  928. }
  929. dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
  930. if (!dbbt_data_page) {
  931. printf("failed to allocate dbbt_data_page\n");
  932. ret = -ENOMEM;
  933. goto dbbt_page_err;
  934. }
  935. dbbt = dbbt_page;
  936. dbbt->checksum = 0;
  937. dbbt->fingerprint = DBBT_FINGERPRINT;
  938. dbbt->version = DBBT_VERSION_1;
  939. ret = fill_dbbt_data(mtd, dbbt_data_page, CONV_TO_BLOCKS(maxsize));
  940. if (ret < 0)
  941. goto dbbt_data_page_err;
  942. else if (ret > 0)
  943. dbbt->dbbtpages = 1;
  944. /* write dbbt */
  945. ret = write_dbbt(&cfg, dbbt, dbbt_data_page);
  946. dbbt_data_page_err:
  947. kfree(dbbt_data_page);
  948. dbbt_page_err:
  949. kfree(dbbt_page);
  950. fcb_err:
  951. kfree(fcb);
  952. if (ret < 0) {
  953. printf("failed to write FCB/DBBT\n");
  954. return CMD_RET_FAILURE;
  955. }
  956. return CMD_RET_SUCCESS;
  957. }
  958. /* dump data which is read from NAND chip */
  959. void dump_structure(struct boot_config *boot_cfg, struct fcb_block *fcb,
  960. struct dbbt_block *dbbt, void *dbbt_data_page)
  961. {
  962. int i;
  963. struct mtd_info *mtd = boot_cfg->mtd;
  964. #define P1(x) printf(" %s = 0x%08x\n", #x, fcb->x)
  965. printf("FCB\n");
  966. P1(checksum);
  967. P1(fingerprint);
  968. P1(version);
  969. #undef P1
  970. #define P1(x) printf(" %s = %d\n", #x, fcb->x)
  971. P1(datasetup);
  972. P1(datahold);
  973. P1(addr_setup);
  974. P1(dsample_time);
  975. P1(pagesize);
  976. P1(oob_pagesize);
  977. P1(sectors);
  978. P1(nr_nand);
  979. P1(nr_die);
  980. P1(celltype);
  981. P1(ecc_type);
  982. P1(ecc_nr);
  983. P1(ecc_size);
  984. P1(ecc_level);
  985. P1(meta_size);
  986. P1(nr_blocks);
  987. P1(ecc_type_sdk);
  988. P1(ecc_nr_sdk);
  989. P1(ecc_size_sdk);
  990. P1(ecc_level_sdk);
  991. P1(nr_blocks_sdk);
  992. P1(meta_size_sdk);
  993. P1(erase_th);
  994. P1(bootpatch);
  995. P1(patch_size);
  996. P1(fw1_start);
  997. P1(fw2_start);
  998. P1(fw1_pages);
  999. P1(fw2_pages);
  1000. P1(dbbt_start);
  1001. P1(bb_byte);
  1002. P1(bb_start_bit);
  1003. P1(phy_offset);
  1004. P1(bchtype);
  1005. P1(readlatency);
  1006. P1(predelay);
  1007. P1(cedelay);
  1008. P1(postdelay);
  1009. P1(cmdaddpause);
  1010. P1(datapause);
  1011. P1(tmspeed);
  1012. P1(busytimeout);
  1013. P1(disbbm);
  1014. P1(spare_offset);
  1015. #if !defined(CONFIG_MX6) || defined(CONFIG_MX6SX) || \
  1016. defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL)
  1017. P1(onfi_sync_enable);
  1018. P1(onfi_sync_speed);
  1019. P1(onfi_sync_nand_data);
  1020. P1(disbbm_search);
  1021. P1(disbbm_search_limit);
  1022. P1(read_retry_enable);
  1023. #endif
  1024. #undef P1
  1025. #define P1(x) printf(" %s = 0x%08x\n", #x, dbbt->x)
  1026. printf("DBBT :\n");
  1027. P1(checksum);
  1028. P1(fingerprint);
  1029. P1(version);
  1030. #undef P1
  1031. #define P1(x) printf(" %s = %d\n", #x, dbbt->x)
  1032. P1(dbbtpages);
  1033. #undef P1
  1034. for (i = 0; i < dbbt->dbbtpages; ++i)
  1035. printf("%d ", *((u32 *)(dbbt_data_page + i)));
  1036. if (!(plat_config.misc_flags & FIRMWARE_EXTRA_ONE)) {
  1037. printf("Firmware: image #0 @ 0x%x size 0x%x\n",
  1038. fcb->fw1_start, fcb->fw1_pages * mtd->writesize);
  1039. printf("Firmware: image #1 @ 0x%x size 0x%x\n",
  1040. fcb->fw2_start, fcb->fw2_pages * mtd->writesize);
  1041. } else {
  1042. printf("Firmware: image #0 @ 0x%x size 0x%x\n",
  1043. fcb->fw1_start, fcb->fw1_pages * mtd->writesize);
  1044. printf("Firmware: image #1 @ 0x%x size 0x%x\n",
  1045. fcb->fw2_start, fcb->fw2_pages * mtd->writesize);
  1046. /* TODO: Add extra image information */
  1047. }
  1048. }
  1049. static bool check_fingerprint(void *data, int fingerprint)
  1050. {
  1051. int off = 4;
  1052. return (*(int *)(data + off) == fingerprint);
  1053. }
  1054. static int fuse_to_search_count(u32 bank, u32 word, u32 mask, u32 off)
  1055. {
  1056. int err;
  1057. u32 val;
  1058. int ret;
  1059. /* by default, the boot search count from fuse should be 2 */
  1060. err = fuse_read(bank, word, &val);
  1061. if (err)
  1062. return 2;
  1063. val = (val & mask) >> off;
  1064. switch (val) {
  1065. case 0:
  1066. ret = 2;
  1067. break;
  1068. case 1:
  1069. case 2:
  1070. case 3:
  1071. ret = 1 << val;
  1072. break;
  1073. default:
  1074. ret = 2;
  1075. }
  1076. return ret;
  1077. }
  1078. static int nandbcb_dump(struct boot_config *boot_cfg)
  1079. {
  1080. int i;
  1081. loff_t off;
  1082. struct mtd_info *mtd = boot_cfg->mtd;
  1083. struct fcb_block fcb, fcb_copy;
  1084. struct dbbt_block dbbt, dbbt_copy;
  1085. void *dbbt_data_page, *dbbt_data_page_copy;
  1086. bool fcb_not_found, dbbt_not_found;
  1087. int ret = 0;
  1088. dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
  1089. if (!dbbt_data_page) {
  1090. printf("failed to allocate dbbt_data_page\n");
  1091. ret = -ENOMEM;
  1092. return ret;
  1093. }
  1094. dbbt_data_page_copy = kzalloc(mtd->writesize, GFP_KERNEL);
  1095. if (!dbbt_data_page_copy) {
  1096. printf("failed to allocate dbbt_data_page\n");
  1097. ret = -ENOMEM;
  1098. goto dbbt_page_err;
  1099. }
  1100. /* read fcb */
  1101. fcb_not_found = 1;
  1102. off = 0;
  1103. for (i = 0; i < g_boot_search_count; ++i) {
  1104. if (fcb_not_found) {
  1105. ret = read_fcb(boot_cfg, &fcb, off);
  1106. if (ret < 0)
  1107. goto dbbt_page_copy_err;
  1108. else if (ret == 1)
  1109. continue;
  1110. else if (ret == 0)
  1111. if (check_fingerprint(&fcb, FCB_FINGERPRINT))
  1112. fcb_not_found = 0;
  1113. } else {
  1114. ret = read_fcb(boot_cfg, &fcb_copy, off);
  1115. if (ret < 0)
  1116. goto dbbt_page_copy_err;
  1117. if (memcmp(&fcb, &fcb_copy,
  1118. sizeof(struct fcb_block))) {
  1119. printf("FCB copies are not identical\n");
  1120. ret = -EINVAL;
  1121. goto dbbt_page_copy_err;
  1122. }
  1123. }
  1124. /* next read location */
  1125. off += g_boot_search_stride;
  1126. }
  1127. /* read dbbt*/
  1128. dbbt_not_found = 1;
  1129. off = boot_cfg->search_area_size_in_bytes;
  1130. for (i = 0; i < g_boot_search_count; ++i) {
  1131. if (dbbt_not_found) {
  1132. ret = read_dbbt(boot_cfg, &dbbt, dbbt_data_page, off);
  1133. if (ret < 0)
  1134. goto dbbt_page_copy_err;
  1135. else if (ret == 1)
  1136. continue;
  1137. else if (ret == 0)
  1138. if (check_fingerprint(&dbbt, DBBT_FINGERPRINT))
  1139. dbbt_not_found = 0;
  1140. } else {
  1141. ret = read_dbbt(boot_cfg, &dbbt_copy,
  1142. dbbt_data_page_copy, off);
  1143. if (ret < 0)
  1144. goto dbbt_page_copy_err;
  1145. if (memcmp(&dbbt, &dbbt_copy,
  1146. sizeof(struct dbbt_block))) {
  1147. printf("DBBT copies are not identical\n");
  1148. ret = -EINVAL;
  1149. goto dbbt_page_copy_err;
  1150. }
  1151. if (dbbt.dbbtpages > 0 &&
  1152. memcmp(dbbt_data_page, dbbt_data_page_copy,
  1153. mtd->writesize)) {
  1154. printf("DBBT data copies are not identical\n");
  1155. ret = -EINVAL;
  1156. goto dbbt_page_copy_err;
  1157. }
  1158. }
  1159. /* next read location */
  1160. off += g_boot_search_stride;
  1161. }
  1162. dump_structure(boot_cfg, &fcb, &dbbt, dbbt_data_page);
  1163. dbbt_page_copy_err:
  1164. kfree(dbbt_data_page_copy);
  1165. dbbt_page_err:
  1166. kfree(dbbt_data_page);
  1167. return ret;
  1168. }
  1169. static int do_nandbcb_dump(int argc, char * const argv[])
  1170. {
  1171. struct boot_config cfg;
  1172. int ret;
  1173. if (argc != 2)
  1174. return CMD_RET_USAGE;
  1175. memset(&cfg, 0, sizeof(struct boot_config));
  1176. if (nandbcb_get_info(argc, argv, &cfg))
  1177. return CMD_RET_FAILURE;
  1178. if (nandbcb_get_size(argc, argv, 1, &cfg))
  1179. return CMD_RET_FAILURE;
  1180. if (nandbcb_set_boot_config(argc, argv, &cfg))
  1181. return CMD_RET_FAILURE;
  1182. ret = nandbcb_dump(&cfg);
  1183. if (ret)
  1184. return ret;
  1185. return ret;
  1186. }
  1187. static int do_nandbcb_init(int argc, char * const argv[])
  1188. {
  1189. u_char *buf;
  1190. size_t size;
  1191. loff_t addr;
  1192. char *endp;
  1193. int ret;
  1194. struct boot_config cfg;
  1195. if (argc != 4)
  1196. return CMD_RET_USAGE;
  1197. memset(&cfg, 0, sizeof(struct boot_config));
  1198. if (nandbcb_get_info(argc, argv, &cfg))
  1199. return CMD_RET_FAILURE;
  1200. if (nandbcb_get_size(argc, argv, 2, &cfg))
  1201. return CMD_RET_FAILURE;
  1202. size = cfg.boot_stream1_size;
  1203. if (nandbcb_set_boot_config(argc, argv, &cfg))
  1204. return CMD_RET_FAILURE;
  1205. addr = simple_strtoul(argv[1], &endp, 16);
  1206. if (*argv[1] == 0 || *endp != 0)
  1207. return CMD_RET_FAILURE;
  1208. buf = map_physmem(addr, size, MAP_WRBACK);
  1209. if (!buf) {
  1210. puts("failed to map physical memory\n");
  1211. return CMD_RET_FAILURE;
  1212. }
  1213. ret = nandbcb_init(&cfg, buf);
  1214. return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  1215. }
  1216. static int do_nandbcb(struct cmd_tbl *cmdtp, int flag, int argc,
  1217. char *const argv[])
  1218. {
  1219. const char *cmd;
  1220. int ret = 0;
  1221. if (argc < 3)
  1222. goto usage;
  1223. /* check the platform config first */
  1224. if (is_mx6sx()) {
  1225. plat_config = imx6sx_plat_config;
  1226. } else if (is_mx7()) {
  1227. plat_config = imx7d_plat_config;
  1228. } else if (is_mx6ul() || is_mx6ull()) {
  1229. plat_config = imx6ul_plat_config;
  1230. } else if (is_mx6() && !is_mx6sx() && !is_mx6ul() && !is_mx6ull()) {
  1231. plat_config = imx6qdl_plat_config;
  1232. } else if (is_imx8mq()) {
  1233. plat_config = imx8mq_plat_config;
  1234. } else if (is_imx8mm()) {
  1235. plat_config = imx8mm_plat_config;
  1236. } else if (is_imx8mn()) {
  1237. plat_config = imx8mn_plat_config;
  1238. } else if (is_imx8qm() || is_imx8qxp()) {
  1239. plat_config = imx8q_plat_config;
  1240. } else {
  1241. printf("ERROR: Unknown platform\n");
  1242. return CMD_RET_FAILURE;
  1243. }
  1244. if (plat_config.misc_flags & BT_SEARCH_CNT_FROM_FUSE) {
  1245. if (is_imx8qxp()) {
  1246. g_boot_search_count = fuse_to_search_count(0, 720,
  1247. 0xc0, 6);
  1248. printf("search count set to %d from fuse\n",
  1249. g_boot_search_count);
  1250. }
  1251. }
  1252. cmd = argv[1];
  1253. --argc;
  1254. ++argv;
  1255. if (strcmp(cmd, "init") == 0) {
  1256. ret = do_nandbcb_init(argc, argv);
  1257. goto done;
  1258. }
  1259. if (strcmp(cmd, "dump") == 0) {
  1260. ret = do_nandbcb_dump(argc, argv);
  1261. goto done;
  1262. }
  1263. if (strcmp(cmd, "bcbonly") == 0) {
  1264. ret = do_nandbcb_bcbonly(argc, argv);
  1265. goto done;
  1266. }
  1267. done:
  1268. if (ret != -1)
  1269. return ret;
  1270. usage:
  1271. return CMD_RET_USAGE;
  1272. }
  1273. #ifdef CONFIG_SYS_LONGHELP
  1274. static char nandbcb_help_text[] =
  1275. "init addr off|partition len - update 'len' bytes starting at\n"
  1276. " 'off|part' to memory address 'addr', skipping bad blocks\n"
  1277. "nandbcb bcbonly off|partition fw1-off fw1-size [fw2-off fw2-size]\n"
  1278. " - write BCB only (FCB and DBBT)\n"
  1279. " where `fwx-size` is fw sizes in bytes, `fw1-off`\n"
  1280. " and `fw2-off` - firmware offsets\n"
  1281. " FIY, BCB isn't erased automatically, so mtd erase should\n"
  1282. " be called in advance before writing new BCB:\n"
  1283. " > mtd erase mx7-bcb\n"
  1284. "nandbcb dump off|partition - dump/verify boot structures\n";
  1285. #endif
  1286. U_BOOT_CMD(nandbcb, 7, 1, do_nandbcb,
  1287. "i.MX NAND Boot Control Blocks write",
  1288. nandbcb_help_text
  1289. );