Index: emcore/trunk/target/ipodnano2g/ftl.c |
— | — | @@ -417,19 +417,21 @@ |
418 | 418 | back if something fails while compacting a scattered page block. */
|
419 | 419 | static uint16_t ftl_offsets_backup[0x200] CACHEALIGN_ATTR;
|
420 | 420 |
|
421 | | -/* Buffers needed for FTL recovery */
|
422 | | -static uint32_t blk_usn[0x2000] INITBSS_ATTR;
|
423 | | -static uint8_t blk_type[0x2000] INITBSS_ATTR;
|
424 | | -static uint32_t erasectr_usn[8] INITBSS_ATTR;
|
425 | | -static uint32_t pageusn[0x200] INITBSS_ATTR;
|
426 | | -static uint8_t pagedata[0x200][0x800] INITBSS_ATTR CACHEALIGN_ATTR;
|
| 421 | +struct nandfsck_bss /* This will be malloc()ed if needed */
|
| 422 | +{
|
| 423 | + /* Buffers needed for FTL recovery */
|
| 424 | + uint32_t blk_usn[0x2000];
|
| 425 | + int8_t blk_type[0x2000];
|
| 426 | + uint32_t erasectr_usn[8];
|
| 427 | + uint32_t pageusn[0x200];
|
| 428 | + uint8_t pagedata[0x200][0x800];
|
427 | 429 |
|
428 | | -/* State information needed for FTL recovery */
|
429 | | -static uint32_t meta_usn INITBSS_ATTR;
|
430 | | -static uint32_t user_usn INITBSS_ATTR;
|
431 | | -static uint32_t allocmode INITBSS_ATTR;
|
432 | | -static uint32_t firstfree INITBSS_ATTR;
|
433 | | -
|
| 430 | + /* State information needed for FTL recovery */
|
| 431 | + uint32_t meta_usn;
|
| 432 | + uint32_t user_usn;
|
| 433 | + uint32_t allocmode;
|
| 434 | + uint32_t firstfree;
|
| 435 | +};
|
434 | 436 | #endif
|
435 | 437 |
|
436 | 438 |
|
— | — | @@ -2236,31 +2238,32 @@ |
2237 | 2239 |
|
2238 | 2240 |
|
2239 | 2241 | /* Block allocator for FTL recovery */
|
2240 | | -static uint32_t ftl_alloc_block() INITCODE_ATTR;
|
2241 | | -static uint32_t ftl_alloc_block()
|
| 2242 | +static uint32_t ftl_alloc_block(struct nandfsck_bss* nb) INITCODE_ATTR;
|
| 2243 | +static uint32_t ftl_alloc_block(struct nandfsck_bss* nb)
|
2242 | 2244 | {
|
2243 | 2245 | while (1)
|
2244 | 2246 | {
|
2245 | | - for (; firstfree < ftl_nand_type->userblocks + 0x17; firstfree++)
|
2246 | | - if (!blk_type[firstfree]) break;
|
2247 | | - else if (allocmode && blk_type[firstfree] != 1)
|
| 2247 | + for (; nb->firstfree < ftl_nand_type->userblocks + 0x17; nb->firstfree++)
|
| 2248 | + if (!nb->blk_type[nb->firstfree]) break;
|
| 2249 | + else if (nb->allocmode && nb->blk_type[nb->firstfree] != 1)
|
2248 | 2250 | {
|
2249 | | - if (ftl_erase_block(firstfree))
|
| 2251 | + if (ftl_erase_block(nb->firstfree))
|
2250 | 2252 | {
|
2251 | | - cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d (pool alloc)!\n", firstfree);
|
| 2253 | + cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d (pool alloc)!\n",
|
| 2254 | + nb->firstfree);
|
2252 | 2255 | return 1;
|
2253 | 2256 | }
|
2254 | 2257 | break;
|
2255 | 2258 | }
|
2256 | | - if (firstfree < ftl_nand_type->userblocks + 0x17)
|
| 2259 | + if (nb->firstfree < ftl_nand_type->userblocks + 0x17)
|
2257 | 2260 | {
|
2258 | | - blk_type[firstfree] = 1;
|
2259 | | - return firstfree++;
|
| 2261 | + nb->blk_type[nb->firstfree] = 1;
|
| 2262 | + return nb->firstfree++;
|
2260 | 2263 | }
|
2261 | | - if (!allocmode)
|
| 2264 | + if (!nb->allocmode)
|
2262 | 2265 | {
|
2263 | | - allocmode = 1;
|
2264 | | - firstfree = 0;
|
| 2266 | + nb->allocmode = 1;
|
| 2267 | + nb->firstfree = 0;
|
2265 | 2268 | }
|
2266 | 2269 | else
|
2267 | 2270 | {
|
— | — | @@ -2279,6 +2282,8 @@ |
2280 | 2283 | struct progressbar_state progressbar;
|
2281 | 2284 | #endif
|
2282 | 2285 |
|
| 2286 | + struct nandfsck_bss* nb = (struct nandfsck_bss*)memalign(0x10, sizeof(struct nandfsck_bss));
|
| 2287 | +
|
2283 | 2288 | cputs(CONSOLE_BOOT, "Scanning flash...\n");
|
2284 | 2289 | #ifdef HAVE_LCD
|
2285 | 2290 | lcdconsole_progressbar(&progressbar, 0, ftl_nand_type->userblocks + 0x17);
|
— | — | @@ -2286,12 +2291,12 @@ |
2287 | 2292 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
|
2288 | 2293 | memset(&ftl_cxt, 0x00, sizeof(ftl_cxt));
|
2289 | 2294 | memset(ftl_map, 0xff, sizeof(ftl_map));
|
2290 | | - memset(blk_usn, 0x00, sizeof(blk_usn));
|
2291 | | - memset(blk_type, 0x00, sizeof(blk_type));
|
| 2295 | + memset(nb->blk_usn, 0x00, sizeof(nb->blk_usn));
|
| 2296 | + memset(nb->blk_type, 0x00, sizeof(nb->blk_type));
|
2292 | 2297 | memset(ftl_erasectr, 0x00, sizeof(ftl_erasectr));
|
2293 | | - memset(erasectr_usn, 0xff, sizeof(erasectr_usn));
|
2294 | | - user_usn = 0;
|
2295 | | - meta_usn = 0xffffffff;
|
| 2298 | + memset(nb->erasectr_usn, 0xff, sizeof(nb->erasectr_usn));
|
| 2299 | + nb->user_usn = 0;
|
| 2300 | + nb->meta_usn = 0xffffffff;
|
2296 | 2301 | for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
|
2297 | 2302 | {
|
2298 | 2303 | uint32_t ret = ftl_vfl_read((i + 1) * ppb - 1, 0, &ftl_sparebuffer[0], 1, 0);
|
— | — | @@ -2298,17 +2303,17 @@ |
2299 | 2304 | if ((ret & 0x11F) == 0 && ftl_sparebuffer[0].meta.type == 0x41)
|
2300 | 2305 | {
|
2301 | 2306 | uint32_t lbn = ftl_sparebuffer[0].user.lpn / ppb;
|
2302 | | - if (ftl_sparebuffer[0].user.usn > user_usn)
|
2303 | | - user_usn = ftl_sparebuffer[0].user.usn;
|
2304 | | - if (ftl_sparebuffer[0].user.usn > blk_usn[lbn])
|
| 2307 | + if (ftl_sparebuffer[0].user.usn > nb->user_usn)
|
| 2308 | + nb->user_usn = ftl_sparebuffer[0].user.usn;
|
| 2309 | + if (ftl_sparebuffer[0].user.usn > nb->blk_usn[lbn])
|
2305 | 2310 | {
|
2306 | 2311 | if (ftl_map[lbn] != 0xffff)
|
2307 | | - blk_type[ftl_map[lbn]] = 5;
|
2308 | | - blk_usn[lbn] = ftl_sparebuffer[0].user.usn;
|
| 2312 | + nb->blk_type[ftl_map[lbn]] = 5;
|
| 2313 | + nb->blk_usn[lbn] = ftl_sparebuffer[0].user.usn;
|
2309 | 2314 | ftl_map[lbn] = i;
|
2310 | | - blk_type[i] = 1;
|
| 2315 | + nb->blk_type[i] = 1;
|
2311 | 2316 | }
|
2312 | | - else blk_type[i] = 5;
|
| 2317 | + else nb->blk_type[i] = 5;
|
2313 | 2318 | }
|
2314 | 2319 | else
|
2315 | 2320 | for (j = 0; j < ppb; j++)
|
— | — | @@ -2317,25 +2322,25 @@ |
2318 | 2323 | if (ret & 2) break;
|
2319 | 2324 | if (ret & 0x11F)
|
2320 | 2325 | {
|
2321 | | - blk_type[i] = 4;
|
| 2326 | + nb->blk_type[i] = 4;
|
2322 | 2327 | continue;
|
2323 | 2328 | }
|
2324 | 2329 | if (ftl_sparebuffer[0].meta.type == 0x40)
|
2325 | 2330 | {
|
2326 | | - blk_type[i] = 2;
|
| 2331 | + nb->blk_type[i] = 2;
|
2327 | 2332 | break;
|
2328 | 2333 | }
|
2329 | 2334 | else if (ftl_sparebuffer[0].meta.type - 0x43 <= 4)
|
2330 | 2335 | {
|
2331 | | - blk_type[i] = 3;
|
| 2336 | + nb->blk_type[i] = 3;
|
2332 | 2337 | if (ftl_sparebuffer[0].meta.type == 0x46)
|
2333 | 2338 | {
|
2334 | 2339 | uint32_t idx = ftl_sparebuffer[0].meta.idx;
|
2335 | | - if (ftl_sparebuffer[0].meta.usn < meta_usn)
|
2336 | | - meta_usn = ftl_sparebuffer[0].meta.usn;
|
2337 | | - if (ftl_sparebuffer[0].meta.usn < erasectr_usn[idx])
|
| 2340 | + if (ftl_sparebuffer[0].meta.usn < nb->meta_usn)
|
| 2341 | + nb->meta_usn = ftl_sparebuffer[0].meta.usn;
|
| 2342 | + if (ftl_sparebuffer[0].meta.usn < nb->erasectr_usn[idx])
|
2338 | 2343 | {
|
2339 | | - erasectr_usn[idx] = ftl_sparebuffer[0].meta.usn;
|
| 2344 | + nb->erasectr_usn[idx] = ftl_sparebuffer[0].meta.usn;
|
2340 | 2345 | ret = ftl_vfl_read(i * ppb + j, &ftl_erasectr[idx << 10],
|
2341 | 2346 | &ftl_sparebuffer[0], 1, 0);
|
2342 | 2347 | if (ret & 0x11f) memset(&ftl_erasectr[idx << 10], 0, 0x800);
|
— | — | @@ -2366,6 +2371,7 @@ |
2367 | 2372 | }
|
2368 | 2373 | }
|
2369 | 2374 | cprintf(CONSOLE_BOOT, "\n");
|
| 2375 | + free(nb);
|
2370 | 2376 | return 1;
|
2371 | 2377 | }
|
2372 | 2378 | }
|
— | — | @@ -2391,7 +2397,7 @@ |
2392 | 2398 | cputs(CONSOLE_BOOT, "Committing scattered pages...\n");
|
2393 | 2399 | count = 0;
|
2394 | 2400 | for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
|
2395 | | - if (blk_type[i] == 2) count++;
|
| 2401 | + if (nb->blk_type[i] == 2) count++;
|
2396 | 2402 | uint32_t block;
|
2397 | 2403 | uint32_t dirty;
|
2398 | 2404 | if (count)
|
— | — | @@ -2401,7 +2407,7 @@ |
2402 | 2408 | #endif
|
2403 | 2409 | count = 0;
|
2404 | 2410 | for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
|
2405 | | - if (blk_type[i] == 2)
|
| 2411 | + if (nb->blk_type[i] == 2)
|
2406 | 2412 | {
|
2407 | 2413 | block = 0xffff;
|
2408 | 2414 | for (j = 0; j < ppb; j++)
|
— | — | @@ -2417,17 +2423,18 @@ |
2418 | 2424 | cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading "
|
2419 | 2425 | "vPage %d (scattered page)!\n",
|
2420 | 2426 | ftl_sparebuffer[0].meta.type, i * ppb + j);
|
| 2427 | + free(nb);
|
2421 | 2428 | return 1;
|
2422 | 2429 | }
|
2423 | 2430 | if (block == 0xffff)
|
2424 | 2431 | {
|
2425 | 2432 | block = ftl_sparebuffer[0].user.lpn / ppb;
|
2426 | | - memset(pageusn, 0x00, 0x800);
|
2427 | | - memset(pagedata, 0x00, 0x100000);
|
| 2433 | + memset(nb->pageusn, 0x00, 0x800);
|
| 2434 | + memset(nb->pagedata, 0x00, 0x100000);
|
2428 | 2435 | if (ftl_map[block] != 0xffff)
|
2429 | 2436 | for (k = 0; k < ppb; k++)
|
2430 | 2437 | {
|
2431 | | - uint32_t ret = ftl_vfl_read(ftl_map[block] * ppb + k, pagedata[k],
|
| 2438 | + uint32_t ret = ftl_vfl_read(ftl_map[block] * ppb + k, nb->pagedata[k],
|
2432 | 2439 | &ftl_copyspare[0], 1, 0);
|
2433 | 2440 | if (ret & 0x11F) continue;
|
2434 | 2441 | if (ftl_copyspare[0].user.type != 0x40
|
— | — | @@ -2437,6 +2444,7 @@ |
2438 | 2445 | "vPage %d (scattered page orig)!\n",
|
2439 | 2446 | ftl_sparebuffer[0].meta.type,
|
2440 | 2447 | ftl_map[block] * ppb + k);
|
| 2448 | + free(nb);
|
2441 | 2449 | return 1;
|
2442 | 2450 | }
|
2443 | 2451 | if (block != ftl_copyspare[0].user.lpn / ppb)
|
— | — | @@ -2445,9 +2453,10 @@ |
2446 | 2454 | "block (vPage %d, LPN %d)!\n",
|
2447 | 2455 | ftl_map[block] * ppb + k,
|
2448 | 2456 | ftl_sparebuffer[0].user.usn);
|
| 2457 | + free(nb);
|
2449 | 2458 | return 1;
|
2450 | 2459 | }
|
2451 | | - pageusn[k] = ftl_copyspare[0].user.usn;
|
| 2460 | + nb->pageusn[k] = ftl_copyspare[0].user.usn;
|
2452 | 2461 | }
|
2453 | 2462 | dirty = 0;
|
2454 | 2463 | }
|
— | — | @@ -2456,15 +2465,16 @@ |
2457 | 2466 | cprintf(CONSOLE_BOOT, "Foreign page in scattered page block "
|
2458 | 2467 | "block (vPage %d, LPN %d)!\n",
|
2459 | 2468 | i * ppb + j, ftl_sparebuffer[0].user.lpn);
|
| 2469 | + free(nb);
|
2460 | 2470 | return 1;
|
2461 | 2471 | }
|
2462 | 2472 | uint32_t idx = ftl_sparebuffer[0].user.lpn % ppb;
|
2463 | | - if (ftl_sparebuffer[0].user.usn > user_usn)
|
2464 | | - user_usn = ftl_sparebuffer[0].user.usn;
|
2465 | | - if (ftl_sparebuffer[0].user.usn > pageusn[idx])
|
| 2473 | + if (ftl_sparebuffer[0].user.usn > nb->user_usn)
|
| 2474 | + nb->user_usn = ftl_sparebuffer[0].user.usn;
|
| 2475 | + if (ftl_sparebuffer[0].user.usn > nb->pageusn[idx])
|
2466 | 2476 | {
|
2467 | | - pageusn[idx] = ftl_sparebuffer[0].user.usn;
|
2468 | | - memcpy(pagedata[idx], ftl_buffer, 0x800);
|
| 2477 | + nb->pageusn[idx] = ftl_sparebuffer[0].user.usn;
|
| 2478 | + memcpy(nb->pagedata[idx], ftl_buffer, 0x800);
|
2469 | 2479 | dirty = 1;
|
2470 | 2480 | }
|
2471 | 2481 | }
|
— | — | @@ -2474,6 +2484,7 @@ |
2475 | 2485 | {
|
2476 | 2486 | cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d "
|
2477 | 2487 | "(scattered page commit)!\n", i);
|
| 2488 | + free(nb);
|
2478 | 2489 | return 1;
|
2479 | 2490 | }
|
2480 | 2491 | for (j = 0; j < ppb; j++)
|
— | — | @@ -2483,21 +2494,22 @@ |
2484 | 2495 | #endif
|
2485 | 2496 | memset(&ftl_sparebuffer[0], 0xFF, 0x40);
|
2486 | 2497 | ftl_sparebuffer[0].user.lpn = block * ppb + j;
|
2487 | | - ftl_sparebuffer[0].user.usn = pageusn[j];
|
| 2498 | + ftl_sparebuffer[0].user.usn = nb->pageusn[j];
|
2488 | 2499 | ftl_sparebuffer[0].user.type = 0x40;
|
2489 | 2500 | if (j == ppb - 1) ftl_sparebuffer[0].user.type = 0x41;
|
2490 | | - if (ftl_vfl_write(i * ppb + j, 1, pagedata[j], &ftl_sparebuffer[0]))
|
| 2501 | + if (ftl_vfl_write(i * ppb + j, 1, nb->pagedata[j], &ftl_sparebuffer[0]))
|
2491 | 2502 | {
|
2492 | 2503 | cprintf(CONSOLE_BOOT, "Couldn't write vPage %d "
|
2493 | 2504 | "(scattered page commit)!\n", i * ppb + j);
|
| 2505 | + free(nb);
|
2494 | 2506 | return 1;
|
2495 | 2507 | }
|
2496 | 2508 | }
|
2497 | | - if (ftl_map[block] != 0xffff) blk_type[ftl_map[block]] = 5;
|
2498 | | - blk_type[i] = 1;
|
| 2509 | + if (ftl_map[block] != 0xffff) nb->blk_type[ftl_map[block]] = 5;
|
| 2510 | + nb->blk_type[i] = 1;
|
2499 | 2511 | ftl_map[block] = i;
|
2500 | 2512 | }
|
2501 | | - else blk_type[i] = 5;
|
| 2513 | + else nb->blk_type[i] = 5;
|
2502 | 2514 | #ifdef HAVE_LCD
|
2503 | 2515 | progressbar_setpos(&progressbar, ++count * ppb * 2, false);
|
2504 | 2516 | #endif
|
— | — | @@ -2505,17 +2517,18 @@ |
2506 | 2518 | }
|
2507 | 2519 |
|
2508 | 2520 | cputs(CONSOLE_BOOT, "Fixing block map...\n");
|
2509 | | - allocmode = 0;
|
2510 | | - firstfree = 0;
|
2511 | | - for (i = 0; i < 3; i++) ftl_cxt.ftlctrlblocks[i] = ftl_alloc_block();
|
2512 | | - for (i = 0; i < 20; i++) ftl_cxt.blockpool[i] = ftl_alloc_block();
|
| 2521 | + nb->allocmode = 0;
|
| 2522 | + nb->firstfree = 0;
|
| 2523 | + for (i = 0; i < 3; i++) ftl_cxt.ftlctrlblocks[i] = ftl_alloc_block(nb);
|
| 2524 | + for (i = 0; i < 20; i++) ftl_cxt.blockpool[i] = ftl_alloc_block(nb);
|
2513 | 2525 | for (i = 0; i < ftl_nand_type->userblocks; i++)
|
2514 | 2526 | if (ftl_map[i] == 0xffff)
|
2515 | | - ftl_map[i] = ftl_alloc_block();
|
2516 | | - ftl_cxt.usn = meta_usn - 1;
|
2517 | | - ftl_cxt.nextblockusn = user_usn + 1;
|
| 2527 | + ftl_map[i] = ftl_alloc_block(nb);
|
| 2528 | + ftl_cxt.usn = nb->meta_usn - 1;
|
| 2529 | + ftl_cxt.nextblockusn = nb->user_usn + 1;
|
2518 | 2530 | ftl_cxt.freecount = 20;
|
2519 | 2531 | ftl_cxt.clean_flag = 1;
|
| 2532 | + free(nb);
|
2520 | 2533 |
|
2521 | 2534 | cputs(CONSOLE_BOOT, "Committing FTL context...\n");
|
2522 | 2535 | uint32_t blockmappages = ftl_nand_type->userblocks >> 10;
|