bmt.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2015. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include <platform/bmt.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34. typedef struct {
  35. char signature[3];
  36. u8 version;
  37. u8 bad_count; // bad block count in pool
  38. u8 mapped_count; // mapped block count in pool
  39. u8 checksum;
  40. u8 reseverd[13];
  41. } phys_bmt_header;
  42. typedef struct {
  43. phys_bmt_header header;
  44. bmt_entry table[MAX_BMT_SIZE];
  45. } phys_bmt_struct;
  46. typedef struct {
  47. char signature[3];
  48. } bmt_oob_data;
  49. static char MAIN_SIGNATURE[] = "BMT";
  50. static char OOB_SIGNATURE[] = "bmt";
  51. #define SIGNATURE_SIZE (3)
  52. #define MAX_DAT_SIZE 0x4000
  53. #define MAX_OOB_SIZE 0x640
  54. extern bool mtk_nand_write_tlc_block_hw(struct nand_chip *chip,
  55. uint8_t *buf, u32 mapped_block);
  56. extern bool mtk_block_istlc(u64 addr);
  57. extern unsigned char g_spare_buf[MAX_OOB_SIZE];
  58. static struct nand_chip *nand_chip_bmt;
  59. #define BLOCK_SIZE_BMT (nand_chip_bmt->sector_size == 512?nand_chip_bmt->erasesize : nand_chip_bmt->erasesize*2)
  60. #define PAGE_SIZE_BMT (nand_chip_bmt->page_size)
  61. #define OFFSET(block) (((u64)block) * BLOCK_SIZE_BMT)
  62. #define PAGE_ADDR(block) ((block) * (BLOCK_SIZE_BMT / PAGE_SIZE_BMT))
  63. /*********************************************************************
  64. * Flash is splited into 2 parts, system part is for normal system *
  65. * system usage, size is system_block_count, another is replace pool *
  66. * +-------------------------------------------------+ *
  67. * | system_block_count | bmt_block_count | *
  68. * +-------------------------------------------------+ *
  69. *********************************************************************/
  70. static u32 total_block_count; // block number in flash
  71. static u32 system_block_count;
  72. static int bmt_block_count; // bmt table size
  73. static int page_per_block; // page per count
  74. static u32 bmt_block_index; // bmt block index
  75. static bmt_struct bmt; // dynamic created global bmt table
  76. __attribute__((aligned(64))) static u8 dat_buf[MAX_DAT_SIZE];
  77. static u8 oob_buf[MAX_OOB_SIZE];
  78. static bool pool_erased;
  79. extern bool nand_erase_hw (u64 offset);
  80. extern bool mark_block_bad_hw(u64 offset);
  81. extern int nand_write_page_hw(u32 page, u8 *dat, u8 *oob);
  82. /***************************************************************
  83. *
  84. * Interface adaptor for preloader/uboot/kernel
  85. * These interfaces operate on physical address, read/write
  86. * physical data.
  87. *
  88. ***************************************************************/
  89. int nand_read_page_bmt(u32 page, u8 * dat, u8 * oob)
  90. {
  91. return nand_exec_read_page_hw(nand_chip_bmt, page, PAGE_SIZE_BMT, dat, oob);
  92. }
  93. bool nand_block_bad_bmt(u64 offset)
  94. {
  95. return nand_block_bad_hw(nand_chip_bmt, offset);
  96. }
  97. // actually uboot should never use the following 3 functions Fix me kai
  98. bool nand_erase_bmt(u64 offset)
  99. {
  100. return nand_erase_hw(offset);
  101. }
  102. int mark_block_bad_bmt(u64 offset)
  103. {
  104. return mark_block_bad_hw(offset);
  105. }
  106. bool nand_write_page_bmt(u32 page, u8 * dat, u8 * oob)
  107. {
  108. return nand_write_page_hw(page, dat, oob);
  109. }
  110. /***************************************************************
  111. * *
  112. * static internal function *
  113. * *
  114. ***************************************************************/
  115. static void dump_bmt_info(bmt_struct * bmt)
  116. {
  117. int i;
  118. dprintf(INFO, "BMT v%d. total %d mapping:\n", bmt->version, bmt->mapped_count);
  119. for (i = 0; i < bmt->mapped_count; i++) {
  120. dprintf(INFO, "\tbad block (0x%x) has been mapped to block (0x%x)\n", bmt->table[i].bad_index, bmt->table[i].mapped_index);
  121. }
  122. }
  123. static bool match_bmt_signature(u8 * dat, u8 * oob)
  124. {
  125. if (memcmp(dat + MAIN_SIGNATURE_OFFSET, MAIN_SIGNATURE, SIGNATURE_SIZE)) {
  126. dprintf(INFO, "[%s]0x%x,0x%x,0x%x,0x%x \n", __FUNCTION__, *((UINT32 *) dat), *(((UINT32 *) dat) + 1), *(((UINT32 *) dat) + 2), *(((UINT32 *) dat) + 3));
  127. return false;
  128. }
  129. if (memcmp(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE)) {
  130. dprintf(INFO, "main signature match, oob signature doesn't match, but ignore\n");
  131. }
  132. return true;
  133. }
  134. static u8 cal_bmt_checksum(phys_bmt_struct * phys_table, int bmt_size)
  135. {
  136. u32 i;
  137. u8 checksum = 0;
  138. u8 *dat = (u8 *) phys_table;
  139. checksum += phys_table->header.version;
  140. checksum += phys_table->header.mapped_count;
  141. dat += sizeof(phys_bmt_header);
  142. for (i = 0; (u32) i < bmt_size * sizeof(bmt_entry); i++) {
  143. checksum += dat[i];
  144. }
  145. return checksum;
  146. }
  147. // return -1 for unmapped block, and bad block index if mapped.
  148. static int is_block_mapped(int index)
  149. {
  150. int i;
  151. for (i = 0; i < bmt.mapped_count; i++) {
  152. if (index == bmt.table[i].mapped_index)
  153. return i;
  154. }
  155. return -1;
  156. }
  157. static bool is_page_used(u8 * dat, u8 * oob)
  158. {
  159. return ((oob[OOB_INDEX_OFFSET] != 0xFF) || (oob[OOB_INDEX_OFFSET + 1] != 0xFF));
  160. }
  161. static bool valid_bmt_data(phys_bmt_struct * phys_table)
  162. {
  163. int i;
  164. u8 checksum = cal_bmt_checksum(phys_table, bmt_block_count);
  165. if (phys_table->header.checksum != checksum) {
  166. dprintf(INFO, "BMT Data checksum error: %x %x %x\n", phys_table->header.checksum, checksum,bmt_block_count);
  167. return false;
  168. }
  169. dprintf(INFO, "BMT Checksum is: 0x%x\n", phys_table->header.checksum);
  170. for (i = 0; i < phys_table->header.mapped_count; i++) {
  171. if (phys_table->table[i].bad_index >= total_block_count || phys_table->table[i].mapped_index >= total_block_count || phys_table->table[i].mapped_index < system_block_count) {
  172. dprintf(CRITICAL, "index error: bad_index: %d, mapped_index: %d\n", phys_table->table[i].bad_index, phys_table->table[i].mapped_index);
  173. return false;
  174. }
  175. }
  176. dprintf(INFO, "Valid BMT, version v%d\n", phys_table->header.version);
  177. return true;
  178. }
  179. static void fill_nand_bmt_buffer(bmt_struct * bmt, u8 * dat, u8 * oob)
  180. {
  181. phys_bmt_struct *phys_bmt = NULL;
  182. phys_bmt = (phys_bmt_struct *)malloc(sizeof(phys_bmt_struct));
  183. if (!phys_bmt) {
  184. ASSERT(0);
  185. }
  186. dump_bmt_info(bmt);
  187. // fill phys_bmt_struct structure with bmt_struct
  188. memset(phys_bmt, 0xFF, sizeof(phys_bmt_struct));
  189. memcpy(phys_bmt->header.signature, MAIN_SIGNATURE, SIGNATURE_SIZE);
  190. phys_bmt->header.version = BMT_VERSION;
  191. // phys_bmt.header.bad_count = bmt->bad_count;
  192. phys_bmt->header.mapped_count = bmt->mapped_count;
  193. memcpy(phys_bmt->table, bmt->table, sizeof(bmt_entry) * bmt_block_count);
  194. phys_bmt->header.checksum = cal_bmt_checksum(phys_bmt, bmt_block_count);
  195. memcpy(dat + MAIN_SIGNATURE_OFFSET, phys_bmt, sizeof(phys_bmt_struct));
  196. memcpy(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE);
  197. free(phys_bmt);
  198. }
  199. // return valid index if found BMT, else return 0
  200. static int load_bmt_data(int start, int pool_size)
  201. {
  202. int bmt_index = start + pool_size - 1;
  203. phys_bmt_struct *phys_table = NULL;
  204. int i;
  205. phys_table = (phys_bmt_struct *)malloc(sizeof(phys_bmt_struct));
  206. if (!phys_table) {
  207. ASSERT(0);
  208. }
  209. dprintf(INFO, "[%s]: begin to search BMT from block 0x%x\n", __FUNCTION__, bmt_index);
  210. dprintf(INFO, "[%s]: bmt_index=0x%x, start=0x%x, pool_size=0x%x, \n", __FUNCTION__, bmt_index, start, pool_size);
  211. for (bmt_index = start + pool_size - 1; bmt_index >= start; bmt_index--) {
  212. dprintf(INFO, "[%s]: bmt_index=0x%x-- ", __FUNCTION__, bmt_index);
  213. if (nand_block_bad_bmt(OFFSET(bmt_index))) {
  214. dprintf(INFO, "Skip bad block: %d\n", bmt_index);
  215. continue;
  216. }
  217. memset(dat_buf, 0xAA, sizeof(dat_buf));
  218. memset(oob_buf, 0xAA, sizeof(oob_buf));
  219. if (!nand_read_page_bmt(PAGE_ADDR(bmt_index), dat_buf, oob_buf)) {
  220. dprintf(CRITICAL, "Error found when read block %d\n", bmt_index);
  221. continue;
  222. }
  223. if (!match_bmt_signature(dat_buf, oob_buf)) {
  224. dprintf(CRITICAL, "[%s]: match_bmt_signature out! \n", __FUNCTION__);
  225. continue;
  226. }
  227. dprintf(INFO, "Match bmt signature @ block: 0x%x\n", bmt_index);
  228. memcpy(phys_table, dat_buf + MAIN_SIGNATURE_OFFSET, sizeof(phys_bmt_struct));
  229. if (!valid_bmt_data(phys_table)) {
  230. dprintf(CRITICAL, "BMT data is not correct %d\n", bmt_index);
  231. continue;
  232. } else {
  233. bmt.mapped_count = phys_table->header.mapped_count;
  234. bmt.version = phys_table->header.version;
  235. memcpy(bmt.table, phys_table->table, bmt.mapped_count * sizeof(bmt_entry));
  236. dprintf(INFO, "bmt found at block: %d, mapped block: %d\n", bmt_index, bmt.mapped_count);
  237. for (i = 0; i < bmt.mapped_count; i++) {
  238. if (!nand_block_bad_bmt(OFFSET(bmt.table[i].bad_index))) {
  239. dprintf(INFO, "block 0x%x is not mark bad, should be power lost last time\n", bmt.table[i].bad_index);
  240. mark_block_bad_bmt(OFFSET(bmt.table[i].bad_index));
  241. }
  242. }
  243. free(phys_table);
  244. return bmt_index;
  245. }
  246. }
  247. free(phys_table);
  248. dprintf(INFO, "bmt block not found!\n");
  249. return 0;
  250. }
  251. /*************************************************************************
  252. * Find an available block and erase. *
  253. * start_from_end: if true, find available block from end of flash. *
  254. * else, find from the beginning of the pool *
  255. * need_erase: if true, all unmapped blocks in the pool will be erased *
  256. *************************************************************************/
  257. static int find_available_block(bool start_from_end)
  258. {
  259. int i; // , j;
  260. u32 block = system_block_count;
  261. int direction;
  262. dprintf(INFO, "Try to find_available_block, pool_erase: %d\n", pool_erased);
  263. if (!pool_erased) {
  264. dprintf(INFO, "Erase all un-mapped blocks in pool\n");
  265. for (i = 0; i < bmt_block_count; i++) {
  266. if (block == bmt_block_index) {
  267. dprintf(INFO, "Skip bmt block 0x%x\n", block);
  268. continue;
  269. }
  270. if (nand_block_bad_bmt(OFFSET(block + i))) {
  271. dprintf(INFO, "Skip bad block 0x%x\n", block + i);
  272. continue;
  273. }
  274. if (is_block_mapped(block + i) >= 0) {
  275. dprintf(INFO, "Skip mapped block 0x%x\n", block + i);
  276. continue;
  277. }
  278. if (!nand_erase_bmt(OFFSET(block + i))) {
  279. dprintf(INFO, "Erase block 0x%x failed\n", block + i);
  280. mark_block_bad_bmt(OFFSET(block + i));
  281. }
  282. }
  283. pool_erased = 1;
  284. }
  285. if (start_from_end) {
  286. block = total_block_count - 1;
  287. direction = -1;
  288. } else {
  289. block = system_block_count;
  290. direction = 1;
  291. }
  292. for (i = 0; i < bmt_block_count; i++, block += direction) {
  293. if ((u32)block == bmt_block_index) {
  294. dprintf(INFO, "Skip bmt block 0x%x\n", block);
  295. continue;
  296. }
  297. if (nand_block_bad_bmt(OFFSET(block))) {
  298. dprintf(INFO, "Skip bad block 0x%x\n", block);
  299. continue;
  300. }
  301. if (is_block_mapped(block) >= 0) {
  302. dprintf(INFO, "Skip mapped block 0x%x\n", block);
  303. continue;
  304. }
  305. dprintf(INFO, "Find block 0x%x available\n", block);
  306. return block;
  307. }
  308. return 0;
  309. }
  310. static unsigned short get_bad_index_from_oob(u8 * oob_buf)
  311. {
  312. unsigned short index;
  313. memcpy(&index, oob_buf + OOB_INDEX_OFFSET, OOB_INDEX_SIZE);
  314. return index;
  315. }
  316. void set_bad_index_to_oob(u8 * oob, u16 index)
  317. {
  318. memcpy(oob + OOB_INDEX_OFFSET, &index, sizeof(index));
  319. }
  320. static int migrate_from_bad(u64 offset, u8 * write_dat, u8 * write_oob)
  321. {
  322. u32 page;
  323. u32 error_block = (u32)(offset / BLOCK_SIZE_BMT);
  324. u32 error_page = (u32)(offset / PAGE_SIZE_BMT) % page_per_block;
  325. int to_index;
  326. memcpy(oob_buf, write_oob, MAX_OOB_SIZE);
  327. to_index = find_available_block(false);
  328. if (!to_index) {
  329. dprintf(INFO, "Cannot find an available block for BMT\n");
  330. return 0;
  331. }
  332. {
  333. // migrate error page first
  334. dprintf(INFO, "Write error page: 0x%x\n", error_page);
  335. if (!write_dat) {
  336. nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL);
  337. write_dat = dat_buf;
  338. }
  339. // memcpy(oob_buf, write_oob, MAX_OOB_SIZE);
  340. if ((u32)error_block < system_block_count)
  341. set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB.
  342. if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) {
  343. dprintf(INFO, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page);
  344. mark_block_bad_bmt(OFFSET(to_index));
  345. return migrate_from_bad(offset, write_dat, write_oob);
  346. }
  347. }
  348. for (page = 0; page < (u32)page_per_block; page++) {
  349. if (page != error_page) {
  350. nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf);
  351. if (is_page_used(dat_buf, oob_buf)) {
  352. if ((u32)error_block < system_block_count) {
  353. set_bad_index_to_oob(oob_buf, error_block);
  354. }
  355. dprintf(INFO, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page);
  356. if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) {
  357. dprintf(INFO, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page);
  358. mark_block_bad_bmt(OFFSET(to_index));
  359. return migrate_from_bad(offset, write_dat, write_oob);
  360. }
  361. }
  362. }
  363. }
  364. dprintf(INFO, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index);
  365. return to_index;
  366. }
  367. static bool write_bmt_to_flash(u8 * dat, u8 * oob)
  368. {
  369. bool need_erase = true;
  370. dprintf(INFO, "Try to write BMT\n");
  371. if (bmt_block_index == 0) {
  372. // if we don't have index, we don't need to erase found block as it has been erased in find_available_block()
  373. need_erase = false;
  374. if (!(bmt_block_index = find_available_block(true))) {
  375. dprintf(INFO, "Cannot find an available block for BMT\n");
  376. return false;
  377. }
  378. }
  379. dprintf(INFO, "Find BMT block: 0x%x\n", bmt_block_index);
  380. if (need_erase) {
  381. if (!nand_erase_bmt(OFFSET(bmt_block_index))) {
  382. dprintf(INFO, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index);
  383. mark_block_bad_bmt(OFFSET(bmt_block_index));
  384. bmt_block_index = 0;
  385. return write_bmt_to_flash(dat, oob); // recursive call
  386. }
  387. }
  388. if (!nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob)) {
  389. dprintf(INFO, "Write BMT data fail, need to write again\n");
  390. mark_block_bad_bmt(OFFSET(bmt_block_index));
  391. // bmt.bad_count++;
  392. bmt_block_index = 0;
  393. return write_bmt_to_flash(dat, oob); // recursive call
  394. }
  395. dprintf(INFO, "Write BMT data to block 0x%x success\n", bmt_block_index);
  396. return true;
  397. }
  398. /*******************************************************************
  399. * Reconstruct bmt, called when found bmt info doesn't match bad
  400. * block info in flash.
  401. *
  402. * Return NULL for failure
  403. *******************************************************************/
  404. bmt_struct *reconstruct_bmt(bmt_struct * bmt)
  405. {
  406. int i;
  407. int index = system_block_count;
  408. unsigned short bad_index;
  409. int mapped;
  410. bmt->version = BMT_VERSION;
  411. bmt->bad_count = 0;
  412. bmt->mapped_count = 0;
  413. memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry));
  414. for (i = 0; i < bmt_block_count; i++, index++) {
  415. if (nand_block_bad_bmt(OFFSET(index))) {
  416. dprintf(INFO, "Skip bad block: 0x%x\n", index);
  417. continue;
  418. }
  419. nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf);
  420. if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count) {
  421. dprintf(INFO, "get bad index: 0x%x\n", bad_index);
  422. if (bad_index != 0xFFFF)
  423. dprintf(INFO, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index);
  424. continue;
  425. }
  426. dprintf(INFO, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index);
  427. if (!nand_block_bad_bmt(OFFSET(bad_index))) {
  428. dprintf(INFO, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index);
  429. continue; // no need to erase here, it will be erased later when trying to write BMT
  430. }
  431. if ((mapped = is_block_mapped(bad_index)) >= 0) {
  432. dprintf(INFO, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index);
  433. bmt->table[mapped].mapped_index = index; // use new one instead.
  434. } else {
  435. bmt->table[bmt->mapped_count].bad_index = bad_index;
  436. bmt->table[bmt->mapped_count].mapped_index = index;
  437. bmt->mapped_count++;
  438. }
  439. dprintf(INFO, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index);
  440. }
  441. dprintf(INFO, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count);
  442. memset(oob_buf, 0xFF, sizeof(oob_buf));
  443. fill_nand_bmt_buffer(bmt, dat_buf, oob_buf);
  444. if (!write_bmt_to_flash(dat_buf, oob_buf)) {
  445. dprintf(INFO, "TRAGEDY: cannot find a place to write BMT!!!!\n");
  446. }
  447. return bmt;
  448. }
  449. /*******************************************************************
  450. * [BMT Interface]
  451. *
  452. * Description:
  453. * Init bmt from nand. Reconstruct if not found or data error
  454. *
  455. * Parameter:
  456. * size: size of bmt and replace pool
  457. *
  458. * Return:
  459. * NULL for failure, and a bmt struct for success
  460. *******************************************************************/
  461. bmt_struct *init_bmt(struct nand_chip * chip, int size)
  462. {
  463. if (size > 0 && size < MAX_BMT_SIZE) {
  464. dprintf(INFO, "Init bmt table, size: %d\n", size);
  465. bmt_block_count = size;
  466. } else {
  467. dprintf(INFO, "Invalid bmt table size: %d\n", size);
  468. return NULL;
  469. }
  470. nand_chip_bmt = chip;
  471. system_block_count = (u32)(chip->chipsize / (chip->sector_size == 512?chip->erasesize : chip->erasesize*2));
  472. total_block_count = bmt_block_count + system_block_count;
  473. page_per_block = (chip->sector_size == 512?chip->erasesize : chip->erasesize*2) / chip->page_size;
  474. dprintf(INFO, "bmt count: %d, system count: %d\n", bmt_block_count, system_block_count);
  475. pool_erased = 0;
  476. memset(bmt.table, 0, size * sizeof(bmt_entry));
  477. if ((bmt_block_index = load_bmt_data(system_block_count, size))) {
  478. dprintf(INFO, "Load bmt data success @ block 0x%x\n", bmt_block_index);
  479. //dump_bmt_info(&bmt);
  480. return &bmt;
  481. } else {
  482. dprintf(INFO, "Load bmt data fail, need re-construct!\n");
  483. if (reconstruct_bmt(&bmt))
  484. return &bmt;
  485. else
  486. return NULL;
  487. }
  488. }
  489. /*******************************************************************
  490. * [BMT Interface]
  491. *
  492. * Description:
  493. * Update BMT.
  494. *
  495. * Parameter:
  496. * offset: update block/page offset.
  497. * reason: update reason, see update_reason_t for reason.
  498. * dat/oob: data and oob buffer for write fail.
  499. *
  500. * Return:
  501. * Return true for success, and false for failure.
  502. *******************************************************************/
  503. bool update_bmt(u64 offset, update_reason_t reason, u8 * dat, u8 * oob)
  504. {
  505. int map_index;
  506. int orig_bad_block = -1;
  507. int i;
  508. u32 bad_index = (u32)(offset / BLOCK_SIZE_BMT);
  509. if (reason == UPDATE_WRITE_FAIL) {
  510. dprintf(INFO, "Write fail, need to migrate\n");
  511. if (!(map_index = migrate_from_bad(offset, dat, oob))) {
  512. dprintf(INFO, "migrate fail\n");
  513. return false;
  514. }
  515. } else {
  516. if (!(map_index = find_available_block(false))) {
  517. dprintf(INFO, "Cannot find block in pool\n");
  518. return false;
  519. }
  520. }
  521. if ((u32)bad_index >= system_block_count) {
  522. for (i = 0; i < bmt_block_count; i++) {
  523. if (bmt.table[i].mapped_index == bad_index) {
  524. orig_bad_block = bmt.table[i].bad_index;
  525. break;
  526. }
  527. }
  528. dprintf(INFO, "Mapped block becomes bad, orig bad block is 0x%x\n", orig_bad_block);
  529. bmt.table[i].mapped_index = map_index;
  530. } else {
  531. bmt.table[bmt.mapped_count].mapped_index = map_index;
  532. bmt.table[bmt.mapped_count].bad_index = bad_index;
  533. bmt.mapped_count++;
  534. }
  535. memset(oob_buf, 0xFF, sizeof(oob_buf));
  536. fill_nand_bmt_buffer(&bmt, dat_buf, oob_buf);
  537. if (!write_bmt_to_flash(dat_buf, oob_buf))
  538. return false;
  539. mark_block_bad_bmt(offset);
  540. return true;
  541. }
  542. /*******************************************************************
  543. * [BMT Interface]
  544. *
  545. * Description:
  546. * Given an block index, return mapped index if it's mapped, else
  547. * return given index.
  548. *
  549. * Parameter:
  550. * index: given an block index. This value cannot exceed
  551. * system_block_count.
  552. *
  553. * Return NULL for failure
  554. *******************************************************************/
  555. u16 get_mapping_block_index(u32 index)
  556. {
  557. int i;
  558. if ((u32)index > system_block_count) {
  559. dprintf(INFO, "Given index exceed: 0x%x > 0x%x\n", index, system_block_count);
  560. return index;
  561. }
  562. for (i = 0; i < bmt.mapped_count; i++) {
  563. if (bmt.table[i].bad_index == index) {
  564. dprintf(INFO, "Redirect 0x%x to 0x%x\n", index, bmt.table[i].mapped_index);
  565. return bmt.table[i].mapped_index;
  566. }
  567. }
  568. return index;
  569. }