cmd_nandbcb.c 37 KB

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