freemyipod r124 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r123‎ | r124 | r125 >
Date:20:21, 13 August 2010
Author:theseven
Status:new
Tags:
Comment:
Integrate nandfsck into the FTL
Modified paths:
  • /embios/trunk/export/syscallapi.h (modified) (history)
  • /embios/trunk/export/syscallwrappers.h (modified) (history)
  • /embios/trunk/lcdconsole.c (modified) (history)
  • /embios/trunk/lcdconsole.h (modified) (history)
  • /embios/trunk/progressbar.c (modified) (history)
  • /embios/trunk/syscallapi.c (modified) (history)
  • /embios/trunk/target/ipodnano2g/ftl.c (modified) (history)
  • /embios/trunk/target/ipodnano2g/ftl.h (modified) (history)

Diff [purge]

Index: embios/trunk/target/ipodnano2g/ftl.c
@@ -29,6 +29,9 @@
3030 #include "thread.h"
3131 #include "panic.h"
3232 #include "debug.h"
 33+#include "console.h"
 34+#include "progressbar.h"
 35+#include "lcdconsole.h"
3336
3437
3538
@@ -362,13 +365,13 @@
363366 uint32_t ftl_banks;
364367
365368 /* Block map, used vor pBlock to vBlock mapping */
366 -static uint16_t ftl_map[0x2000];
 369+static uint16_t ftl_map[0x2000] CACHEALIGN_ATTR;
367370
368371 /* VFL context for each bank */
369372 static struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
370373
371374 /* FTL context */
372 -static struct ftl_cxt_type ftl_cxt;
 375+static struct ftl_cxt_type ftl_cxt CACHEALIGN_ATTR;
373376
374377 /* Temporary data buffers for internal use by the FTL */
375378 static uint8_t ftl_buffer[0x800] CACHEALIGN_ATTR;
@@ -383,7 +386,7 @@
384387 static uint8_t ftl_bbt[4][0x410];
385388
386389 /* Erase counters for the vBlocks */
387 -static uint16_t ftl_erasectr[0x2000];
 390+static uint16_t ftl_erasectr[0x2000] CACHEALIGN_ATTR;
388391
389392 /* Used by ftl_log */
390393 static uint16_t ftl_offsets[0x11][0x200];
@@ -411,6 +414,19 @@
412415 back if something fails while compacting a scattered page block. */
413416 static uint16_t ftl_offsets_backup[0x200] CACHEALIGN_ATTR;
414417
 418+/* Buffers needed for FTL recovery */
 419+static uint32_t blk_usn[0x2000] INITBSS_ATTR;
 420+static uint8_t blk_type[0x2000] INITBSS_ATTR;
 421+static uint32_t erasectr_usn[8] INITBSS_ATTR;
 422+static uint32_t pageusn[0x200] INITBSS_ATTR;
 423+static uint8_t pagedata[0x200][0x800] INITBSS_ATTR CACHEALIGN_ATTR;
 424+
 425+/* State information needed for FTL recovery */
 426+static uint32_t meta_usn INITBSS_ATTR;
 427+static uint32_t user_usn INITBSS_ATTR;
 428+static uint32_t allocmode INITBSS_ATTR;
 429+static uint32_t firstfree INITBSS_ATTR;
 430+
415431 #endif
416432
417433
@@ -420,6 +436,7 @@
421437
422438 /* Finds a device info page for the specified bank and returns its number.
423439 Used to check if one is present, and to read the lowlevel BBT. */
 440+static uint32_t ftl_find_devinfo(uint32_t bank) INITCODE_ATTR;
424441 static uint32_t ftl_find_devinfo(uint32_t bank)
425442 {
426443 /* Scan the last 10% of the flash for device info pages */
@@ -444,6 +461,7 @@
445462
446463
447464 /* Checks if all banks have proper device info pages */
 465+static uint32_t ftl_has_devinfo(void) INITCODE_ATTR;
448466 static uint32_t ftl_has_devinfo(void)
449467 {
450468 uint32_t i;
@@ -454,6 +472,7 @@
455473
456474 /* Loads the lowlevel BBT for a bank to the specified buffer.
457475 This is based on some cryptic disassembly and not fully understood yet. */
 476+static uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt) INITCODE_ATTR;
458477 static uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt)
459478 {
460479 uint32_t i, j;
@@ -604,6 +623,7 @@
605624 /* Returns a pointer to the most recently updated VFL context,
606625 used to find out the current FTL context vBlock numbers
607626 (planetbeing's "maxthing") */
 627+static struct ftl_vfl_cxt_type* ftl_vfl_get_newest_cxt(void) INITCODE_ATTR;
608628 static struct ftl_vfl_cxt_type* ftl_vfl_get_newest_cxt(void)
609629 {
610630 uint32_t i, maxusn;
@@ -621,6 +641,7 @@
622642
623643 /* Checks if the specified pBlock is marked bad in the supplied lowlevel BBT.
624644 Only used while mounting the VFL. */
 645+static uint32_t ftl_is_good_block(uint8_t* bbt, uint32_t block) INITCODE_ATTR;
625646 static uint32_t ftl_is_good_block(uint8_t* bbt, uint32_t block)
626647 {
627648 if ((bbt[block >> 3] & (1 << (block & 7))) == 0) return 0;
@@ -652,6 +673,9 @@
653674 /* Tries to read a VFL context from the specified bank, pBlock and page */
654675 static uint32_t ftl_vfl_read_page(uint32_t bank, uint32_t block,
655676 uint32_t startpage, void* databuffer,
 677+ union ftl_spare_data_type* sparebuffer) INITCODE_ATTR;
 678+static uint32_t ftl_vfl_read_page(uint32_t bank, uint32_t block,
 679+ uint32_t startpage, void* databuffer,
656680 union ftl_spare_data_type* sparebuffer)
657681 {
658682 uint32_t i;
@@ -1019,7 +1043,8 @@
10201044
10211045
10221046 /* Mounts the VFL on all banks */
1023 -static uint32_t ftl_vfl_open(void)
 1047+static uint32_t ftl_vfl_open(void) INITCODE_ATTR;
 1048+static uint32_t ftl_vfl_open()
10241049 {
10251050 uint32_t i, j, k;
10261051 uint32_t minusn, vflcxtidx, last;
@@ -1112,7 +1137,8 @@
11131138
11141139
11151140 /* Mounts the actual FTL */
1116 -static uint32_t ftl_open(void)
 1141+static uint32_t ftl_open(void) INITCODE_ATTR;
 1142+static uint32_t ftl_open()
11171143 {
11181144 uint32_t i;
11191145 uint32_t ret;
@@ -1227,7 +1253,7 @@
12281254 {
12291255 uint32_t badblocks = 0;
12301256 #ifndef FTL_READONLY
1231 - for (j = 0; j < (*ftl_nand_type).blocks >> 3; j++)
 1257+ for (j = 0; j < ftl_nand_type->blocks >> 3; j++)
12321258 {
12331259 uint8_t bbtentry = ftl_bbt[i][j];
12341260 for (k = 0; k < 8; k++) if ((bbtentry & (1 << k)) == 0) badblocks++;
@@ -1246,7 +1272,7 @@
12471273 }
12481274 #ifndef FTL_READONLY
12491275 uint32_t min = 0xFFFFFFFF, max = 0, total = 0;
1250 - for (i = 0; i < (*ftl_nand_type).userblocks + 23; i++)
 1276+ for (i = 0; i < ftl_nand_type->userblocks + 23; i++)
12511277 {
12521278 if (ftl_erasectr[i] > max) max = ftl_erasectr[i];
12531279 if (ftl_erasectr[i] < min) min = ftl_erasectr[i];
@@ -1253,7 +1279,7 @@
12541280 total += ftl_erasectr[i];
12551281 }
12561282 DEBUGF("FTL: Erase counters: Minimum: %d, maximum %d, average: %d, total: %d",
1257 - min, max, total / ((*ftl_nand_type).userblocks + 23), total);
 1283+ min, max, total / (ftl_nand_type->userblocks + 23), total);
12581284 #endif
12591285 #endif
12601286
@@ -2167,10 +2193,313 @@
21682194 #endif
21692195
21702196
 2197+/* Block allocator for FTL recovery */
 2198+static uint32_t ftl_alloc_block() INITCODE_ATTR;
 2199+static uint32_t ftl_alloc_block()
 2200+{
 2201+ while (1)
 2202+ {
 2203+ for (; firstfree < ftl_nand_type->userblocks + 0x17; firstfree++)
 2204+ if (!blk_type[firstfree]) break;
 2205+ else if (allocmode && blk_type[firstfree] != 1)
 2206+ {
 2207+ if (ftl_erase_block(firstfree))
 2208+ {
 2209+ cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d (pool alloc)!\n", firstfree);
 2210+ return 1;
 2211+ }
 2212+ break;
 2213+ }
 2214+ if (firstfree < ftl_nand_type->userblocks + 0x17)
 2215+ {
 2216+ blk_type[firstfree] = 1;
 2217+ return firstfree++;
 2218+ }
 2219+ if (!allocmode)
 2220+ {
 2221+ allocmode = 1;
 2222+ firstfree = 0;
 2223+ }
 2224+ else
 2225+ {
 2226+ cputs(CONSOLE_BOOT, "Out of empty blocks!\n");
 2227+ return 1;
 2228+ }
 2229+ }
 2230+}
 2231+
 2232+
 2233+static uint32_t ftl_repair(void) INITCODE_ATTR;
 2234+static uint32_t ftl_repair()
 2235+{
 2236+ uint32_t i, j, k;
 2237+#ifdef HAVE_LCD
 2238+ struct progressbar_state progressbar;
 2239+#endif
 2240+
 2241+ cputs(CONSOLE_BOOT, "Scanning flash...\n");
 2242+#ifdef HAVE_LCD
 2243+ lcdconsole_progressbar(&progressbar, 0, ftl_nand_type->userblocks + 0x17);
 2244+#endif
 2245+ uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
 2246+ memset(&ftl_cxt, 0x00, 0x800);
 2247+ memset(ftl_map, 0xff, 0x4000);
 2248+ memset(blk_usn, 0x00, 0x8000);
 2249+ memset(blk_type, 0x00, 0x2000);
 2250+ memset(ftl_erasectr, 0x00, 0x4000);
 2251+ memset(erasectr_usn, 0xff, 32);
 2252+ user_usn = 0;
 2253+ meta_usn = 0xffffffff;
 2254+ for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
 2255+ {
 2256+ uint32_t ret = ftl_vfl_read((i + 1) * ppb - 1, 0, &ftl_sparebuffer[0], 1, 0);
 2257+ if ((ret & 0x11F) == 0 && ftl_sparebuffer[0].meta.type == 0x41)
 2258+ {
 2259+ uint32_t lbn = ftl_sparebuffer[0].user.lpn / ppb;
 2260+ if (ftl_sparebuffer[0].user.usn > user_usn)
 2261+ user_usn = ftl_sparebuffer[0].user.usn;
 2262+ if (ftl_sparebuffer[0].user.usn > blk_usn[lbn])
 2263+ {
 2264+ if (ftl_map[lbn] != 0xffff)
 2265+ blk_type[ftl_map[lbn]] = 5;
 2266+ blk_usn[lbn] = ftl_sparebuffer[0].user.usn;
 2267+ ftl_map[lbn] = i;
 2268+ blk_type[i] = 1;
 2269+ }
 2270+ else blk_type[i] = 5;
 2271+ }
 2272+ else
 2273+ for (j = 0; j < ppb; j++)
 2274+ {
 2275+ ret = ftl_vfl_read(i * ppb + j, 0, &ftl_sparebuffer[0], 1, 0);
 2276+ if (ret & 2) break;
 2277+ if (ret & 0x11F)
 2278+ {
 2279+ blk_type[i] = 4;
 2280+ continue;
 2281+ }
 2282+ if (ftl_sparebuffer[0].meta.type == 0x40)
 2283+ {
 2284+ blk_type[i] = 2;
 2285+ break;
 2286+ }
 2287+ else if (ftl_sparebuffer[0].meta.type - 0x43 <= 4)
 2288+ {
 2289+ blk_type[i] = 3;
 2290+ if (ftl_sparebuffer[0].meta.type == 0x46)
 2291+ {
 2292+ uint32_t idx = ftl_sparebuffer[0].meta.idx;
 2293+ if (ftl_sparebuffer[0].meta.usn < meta_usn)
 2294+ meta_usn = ftl_sparebuffer[0].meta.usn;
 2295+ if (ftl_sparebuffer[0].meta.usn < erasectr_usn[idx])
 2296+ {
 2297+ erasectr_usn[idx] = ftl_sparebuffer[0].meta.usn;
 2298+ ret = ftl_vfl_read(i * ppb + j, &ftl_erasectr[idx << 10],
 2299+ &ftl_sparebuffer[0], 1, 0);
 2300+ if (ret & 0x11f) memset(&ftl_erasectr[idx << 10], 0, 0x800);
 2301+ }
 2302+ }
 2303+ }
 2304+ else
 2305+ {
 2306+ cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading vPage %d\n",
 2307+ ftl_sparebuffer[0].meta.type, i * ppb + j);
 2308+ return 1;
 2309+ }
 2310+ }
 2311+#ifdef HAVE_LCD
 2312+ progressbar_setpos(&progressbar, i + 1, false);
 2313+#endif
 2314+ }
 2315+
 2316+ uint32_t sum = 0;
 2317+ uint32_t count = 0;
 2318+ for (i = 0; i < 0x2000; i++)
 2319+ if (ftl_erasectr[i])
 2320+ {
 2321+ sum += ftl_erasectr[i];
 2322+ count++;
 2323+ }
 2324+ uint32_t average = sum / count;
 2325+ for (i = 0; i < 0x2000; i++)
 2326+ if (!ftl_erasectr[i])
 2327+ ftl_erasectr[i] = average;
 2328+
 2329+ cputs(CONSOLE_BOOT, "Committing scattered pages...\n");
 2330+ count = 0;
 2331+ for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
 2332+ if (blk_type[i] == 2) count++;
 2333+ uint32_t block;
 2334+ uint32_t dirty;
 2335+ if (count)
 2336+ {
 2337+#ifdef HAVE_LCD
 2338+ lcdconsole_progressbar(&progressbar, 0, count * ppb);
 2339+#endif
 2340+ count = 0;
 2341+ for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
 2342+ if (blk_type[i] == 2)
 2343+ {
 2344+ block = 0xffff;
 2345+ for (j = 0; j < ftl_nand_type->pagesperblock * ftl_banks; j++)
 2346+ {
 2347+ uint32_t ret = ftl_vfl_read(i * ppb + j, ftl_buffer,
 2348+ &ftl_sparebuffer[0], 1, 0);
 2349+ if (ret & 0x11F) continue;
 2350+ if (ftl_sparebuffer[0].user.type != 0x40)
 2351+ {
 2352+ cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading "
 2353+ "vPage %d (scattered page)!\n",
 2354+ ftl_sparebuffer[0].meta.type, i * ppb + j);
 2355+ return 1;
 2356+ }
 2357+ if (block == 0xffff)
 2358+ {
 2359+ block = ftl_sparebuffer[0].user.lpn / ppb;
 2360+ memset(pageusn, 0x00, 0x800);
 2361+ memset(pagedata, 0x00, 0x100000);
 2362+ if (ftl_map[block] != 0xffff)
 2363+ for (k = 0; k < ppb; k++)
 2364+ {
 2365+ uint32_t ret = ftl_vfl_read(ftl_map[block] * ppb + k, pagedata[k],
 2366+ &ftl_copyspare[0], 1, 0);
 2367+ if (ret & 0x11F) continue;
 2368+ if (ftl_copyspare[0].user.type != 0x40
 2369+ && ftl_copyspare[0].user.type != 0x41)
 2370+ {
 2371+ cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading "
 2372+ "vPage %d (scattered page orig)!\n",
 2373+ ftl_sparebuffer[0].meta.type,
 2374+ ftl_map[block] * ppb + k);
 2375+ return 1;
 2376+ }
 2377+ if (block != ftl_copyspare[0].user.lpn / ppb)
 2378+ {
 2379+ cprintf(CONSOLE_BOOT, "Foreign page in scattered page orig "
 2380+ "block (vPage %d, LPN %d)!\n",
 2381+ ftl_map[block] * ppb + k,
 2382+ ftl_sparebuffer[0].user.usn);
 2383+ return 1;
 2384+ }
 2385+ pageusn[k] = ftl_copyspare[0].user.usn;
 2386+ }
 2387+ dirty = 0;
 2388+ }
 2389+ if (block != ftl_sparebuffer[0].user.lpn / ppb)
 2390+ {
 2391+ cprintf(CONSOLE_BOOT, "Foreign page in scattered page block "
 2392+ "block (vPage %d, LPN %d)!\n",
 2393+ i * ppb + j, ftl_sparebuffer[0].user.lpn);
 2394+ return 1;
 2395+ }
 2396+ uint32_t idx = ftl_sparebuffer[0].user.lpn % ppb;
 2397+ if (ftl_sparebuffer[0].user.usn > user_usn)
 2398+ user_usn = ftl_sparebuffer[0].user.usn;
 2399+ if (ftl_sparebuffer[0].user.usn > pageusn[idx])
 2400+ {
 2401+ pageusn[idx] = ftl_sparebuffer[0].user.usn;
 2402+ memcpy(pagedata[idx], ftl_buffer, 0x800);
 2403+ dirty = 1;
 2404+ }
 2405+ }
 2406+ if (dirty)
 2407+ {
 2408+ if (ftl_erase_block(i))
 2409+ {
 2410+ cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d "
 2411+ "(scattered page commit)!\n", i);
 2412+ return 1;
 2413+ }
 2414+ for (j = 0; j < ppb; j++)
 2415+ {
 2416+ memset(&ftl_sparebuffer[0], 0xFF, 0x40);
 2417+ ftl_sparebuffer[0].user.lpn = block * ppb + j;
 2418+ ftl_sparebuffer[0].user.usn = pageusn[j];
 2419+ ftl_sparebuffer[0].user.type = 0x40;
 2420+ if (j == ppb - 1) ftl_sparebuffer[0].user.type = 0x41;
 2421+ if (ftl_vfl_write(i * ppb + j, 1, pagedata[j], &ftl_sparebuffer[0]))
 2422+ {
 2423+ cprintf(CONSOLE_BOOT, "Couldn't write vPage %d "
 2424+ "(scattered page commit)!\n", i * ppb + j);
 2425+ return 1;
 2426+ }
 2427+#ifdef HAVE_LCD
 2428+ progressbar_setpos(&progressbar, count * ppb + j, false);
 2429+#endif
 2430+ }
 2431+ if (ftl_map[block] != 0xffff) blk_type[ftl_map[block]] = 5;
 2432+ blk_type[i] = 1;
 2433+ ftl_map[block] = i;
 2434+ }
 2435+ else blk_type[i] = 5;
 2436+#ifdef HAVE_LCD
 2437+ progressbar_setpos(&progressbar, ++count * ppb, false);
 2438+#endif
 2439+ }
 2440+ }
 2441+
 2442+ cputs(CONSOLE_BOOT, "Fixing block map...\n");
 2443+ allocmode = 0;
 2444+ firstfree = 0;
 2445+ for (i = 0; i < 3; i++) ftl_cxt.ftlctrlblocks[i] = ftl_alloc_block();
 2446+ for (i = 0; i < 20; i++) ftl_cxt.blockpool[i] = ftl_alloc_block();
 2447+ for (i = 0; i < ftl_nand_type->userblocks; i++)
 2448+ if (ftl_map[i] == 0xffff)
 2449+ ftl_map[i] = ftl_alloc_block();
 2450+ ftl_cxt.usn = meta_usn - 1;
 2451+ ftl_cxt.nextblockusn = user_usn + 1;
 2452+ ftl_cxt.freecount = 20;
 2453+ ftl_cxt.clean_flag = 1;
 2454+
 2455+ cputs(CONSOLE_BOOT, "Committing FTL context...\n");
 2456+ uint32_t blockmappages = ftl_nand_type->userblocks >> 10;
 2457+ if ((ftl_nand_type->userblocks & 0x1FF) != 0) blockmappages++;
 2458+ uint32_t erasectrpages = (ftl_nand_type->userblocks + 23) >> 10;
 2459+ if (((ftl_nand_type->userblocks + 23) & 0x1FF) != 0) erasectrpages++;
 2460+ uint32_t page = ftl_cxt.ftlctrlblocks[0] * ppb;
 2461+ for (i = 0; i < erasectrpages; i++)
 2462+ {
 2463+ memset(&ftl_sparebuffer, 0xFF, 0x40);
 2464+ ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
 2465+ ftl_sparebuffer[0].meta.idx = i;
 2466+ ftl_sparebuffer[0].meta.type = 0x46;
 2467+ if (ftl_vfl_write(page, 1, &ftl_erasectr[i << 10], &ftl_sparebuffer[0]))
 2468+ {
 2469+ cprintf(CONSOLE_BOOT, "Couldn't write vPage %d (save erase counters)!\n", page);
 2470+ return 1;
 2471+ }
 2472+ ftl_cxt.ftl_erasectr_pages[i] = page++;
 2473+ }
 2474+ for (i = 0; i < blockmappages; i++)
 2475+ {
 2476+ memset(&ftl_sparebuffer[0], 0xFF, 0x40);
 2477+ ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
 2478+ ftl_sparebuffer[0].meta.idx = i;
 2479+ ftl_sparebuffer[0].meta.type = 0x44;
 2480+ if (ftl_vfl_write(page, 1, &ftl_map[i << 10], &ftl_sparebuffer[0]))
 2481+ {
 2482+ cprintf(CONSOLE_BOOT, "Couldn't write vPage %d (save block map)!\n", page);
 2483+ return 1;
 2484+ }
 2485+ ftl_cxt.ftl_map_pages[i] = page++;
 2486+ }
 2487+ ftl_cxt.ftlctrlpage = page;
 2488+ memset(&ftl_sparebuffer[0], 0xFF, 0x40);
 2489+ ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
 2490+ ftl_sparebuffer[0].meta.type = 0x43;
 2491+ if (ftl_vfl_write(page, 1, &ftl_cxt, &ftl_sparebuffer[0]))
 2492+ {
 2493+ cprintf(CONSOLE_BOOT, "Couldn't write vPage %d (save FTL context)!\n", page);
 2494+ return 1;
 2495+ }
 2496+ ftl_store_ctrl_block_list();
 2497+}
 2498+
 2499+
21712500 /* Initializes and mounts the FTL.
21722501 As long as nothing was written, you won't need to unmount it.
21732502 Before shutting down after writing something, call ftl_sync(),
2174 - which will just do nothing if everything was already clean. */
 2503+ which will return immediately if everything was already clean. */
21752504 uint32_t ftl_init(void)
21762505 {
21772506 mutex_init(&ftl_mtx);
@@ -2214,8 +2543,20 @@
22152544 return 1;
22162545 }
22172546 if (ftl_vfl_open() == 0)
 2547+ {
22182548 if (ftl_open() == 0)
22192549 return 0;
 2550+ cprintf(CONSOLE_BOOT, "The FTL seems to be damaged. Forcing check.\n");
 2551+ if (ftl_repair() != 0)
 2552+ cprintf(CONSOLE_BOOT, "FTL recovery failed. Use disk mode to recover.\n");
 2553+ else
 2554+ {
 2555+ cprintf(CONSOLE_BOOT, "FTL recovery finished. Trying to mount again...\n");
 2556+ if (ftl_open() == 0)
 2557+ return 0;
 2558+ cprintf(CONSOLE_BOOT, "Mounting FTL failed again, use disk mode to recover.\n");
 2559+ }
 2560+ }
22202561
22212562 DEBUGF("FTL: Initialization failed!");
22222563
Index: embios/trunk/target/ipodnano2g/ftl.h
@@ -31,7 +31,7 @@
3232 extern uint32_t ftl_banks;
3333
3434
35 -uint32_t ftl_init(void);
 35+uint32_t ftl_init(void) INITCODE_ATTR;
3636 uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer);
3737 uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer);
3838 uint32_t ftl_sync(void);
Index: embios/trunk/progressbar.c
@@ -26,10 +26,10 @@
2727 #include "lcd.h"
2828
2929
30 -static void progressbar_drawborderbg(struct progressbar_state* state)
 30+static void progressbar_drawborderbg(struct progressbar_state* state, int bgstart)
3131 {
3232 state->currentx = state->startx;
33 - displaylcd(state->startx + 1, state->endx - 1, state->starty + 1, state->endy - 1,
 33+ displaylcd(bgstart + 1, state->endx - 1, state->starty + 1, state->endy - 1,
3434 (void*)-1, state->bgcolor);
3535 displaylcd(state->startx, state->endx, state->starty, state->starty,
3636 (void*)-1, state->bordercolor);
@@ -53,7 +53,7 @@
5454 state->fgcolor = fgcolor;
5555 state->min = min;
5656 state->max = max;
57 - progressbar_drawborderbg(state);
 57+ progressbar_drawborderbg(state, state->startx);
5858 }
5959
6060 void progressbar_setpos(struct progressbar_state* state, int value, bool redraw)
@@ -62,7 +62,7 @@
6363 if (value < state->min) value = state->min;
6464 int newx = (value - state->min) * (state->endx - state->startx - 1)
6565 / (state->max - state->min) + state->startx;
66 - if (redraw || newx < state->currentx) progressbar_drawborderbg(state);
 66+ if (redraw || newx < state->currentx) progressbar_drawborderbg(state, newx);
6767 if (newx > state->currentx)
6868 displaylcd(state->currentx + 1, newx, state->starty + 1, state->endy - 1,
6969 (void*)-1, state->fgcolor);
Index: embios/trunk/export/syscallwrappers.h
@@ -75,6 +75,7 @@
7676 #define lcdconsole_get_current_y(args...) __embios_syscall->lcdconsole_get_current_y(args)
7777 #define lcdconsole_get_lineend_x(args...) __embios_syscall->lcdconsole_get_lineend_x(args)
7878 #define lcdconsole_get_lineend_y(args...) __embios_syscall->lcdconsole_get_lineend_y(args)
 79+#define lcdconsole_progressbar(args...) __embios_syscall->lcdconsole_progressbar(args)
7980 #define progressbar_init(args...) __embios_syscall->progressbar_init(args)
8081 #define progressbar_setpos(args...) __embios_syscall->progressbar_setpos(args)
8182 #define shutdown(args...) __embios_syscall->shutdown(args)
Index: embios/trunk/export/syscallapi.h
@@ -112,6 +112,7 @@
113113 typeof(lcdconsole_get_current_y) *lcdconsole_get_current_y;
114114 typeof(lcdconsole_get_lineend_x) *lcdconsole_get_lineend_x;
115115 typeof(lcdconsole_get_lineend_y) *lcdconsole_get_lineend_y;
 116+ typeof(lcdconsole_progressbar) *lcdconsole_progressbar;
116117 typeof(progressbar_init) *progressbar_init;
117118 typeof(progressbar_setpos) *progressbar_setpos;
118119 typeof(shutdown) *shutdown;
Index: embios/trunk/syscallapi.c
@@ -133,6 +133,7 @@
134134 .lcdconsole_get_current_y = lcdconsole_get_current_y,
135135 .lcdconsole_get_lineend_x = lcdconsole_get_lineend_x,
136136 .lcdconsole_get_lineend_y = lcdconsole_get_lineend_y,
 137+ .lcdconsole_progressbar = lcdconsole_progressbar,
137138 .progressbar_init = progressbar_init,
138139 .progressbar_setpos = progressbar_setpos,
139140 .displaylcd = displaylcd,
Index: embios/trunk/lcdconsole.c
@@ -26,6 +26,7 @@
2727 #include "drawing.h"
2828 #include "util.h"
2929 #include "contextswitch.h"
 30+#include "progressbar.h"
3031
3132
3233 #define OFFSETX LCDCONSOLE_OFFSETX
@@ -153,3 +154,11 @@
154155 {
155156 return (current_row + 1) * FONT_HEIGHT + OFFSETY - 1;
156157 }
 158+
 159+void lcdconsole_progressbar(struct progressbar_state* progressbar, int min, int max)
 160+{
 161+ progressbar_init(progressbar, lcdconsole_get_current_x(), lcdconsole_get_lineend_x(),
 162+ lcdconsole_get_current_y(), lcdconsole_get_lineend_y(),
 163+ lcd_translate_color(0, 0, 0, 0), lcd_translate_color(0, 0xcf, 0xcf, 0xcf),
 164+ lcd_translate_color(0, 0, 0, 0xef), min, max);
 165+}
Index: embios/trunk/lcdconsole.h
@@ -28,6 +28,7 @@
2929 #include "global.h"
3030 #include "drawing.h"
3131 #include "lcd.h"
 32+#include "progressbar.h"
3233
3334
3435 #define LCDCONSOLE_COLS (LCD_WIDTH / FONT_WIDTH)
@@ -49,6 +50,7 @@
5051 int lcdconsole_get_current_y() ICODE_ATTR;
5152 int lcdconsole_get_lineend_x() ICODE_ATTR;
5253 int lcdconsole_get_lineend_y() ICODE_ATTR;
 54+void lcdconsole_progressbar(struct progressbar_state* progressbar, int min, int max);
5355
5456
5557 #endif