Rev 424 | Blame | Last modification | View Log | RSS feed
#include <stdio.h>#include <stdint.h>#include <stdbool.h>#include <fcntl.h>static void mark_bad(uint32_t* bitmap, int sector){bitmap[sector >> 5] &= ~(1 << (sector & 31));}static bool is_good(uint32_t* bitmap, int sector){return bitmap[sector >> 5] & (1 << (sector & 31));}int main(int argc, char** argv){int sectors;sscanf(argv[3], "%i", §ors);size_t bitmapsize = ((sectors + 65535) & ~0xffff) >> 3;uint32_t* bitmap = malloc(bitmapsize);memset(bitmap, 0xff, bitmapsize);FILE* in = fopen(argv[1], "r");if (!in){perror("Failed to open input file");return 2;}char line[256];while (fgets(line, sizeof(line), in)){int sector;if (sscanf(line, "%i", §or) == 1 && sector) mark_bad(bitmap, sector);}fclose(in);int l0count = (sectors + 0x7ffff) >> 19;int bbtpages = 64 + ((l0count + 0x3f) & ~0x3f);int bbtsize;uint16_t (*bbt)[0x20];bool success = false;while (bbtpages <= 32832){bbtsize = bbtpages << 6;bbt = malloc(bbtsize);memset(bbt, 0, bbtsize);int logical = 0;int physical = 1;int remapbase;int bbtgood;for (bbtgood = 0; bbtgood < (bbtpages >> 6) - 1; physical++)if (is_good(bitmap, physical)){((uint32_t*)bbt)[0x200 + bbtgood] = physical;bbtgood++;}int bbtused = 64 + l0count;int level;uint16_t *l1, *l2, *l3;int l1count = 0, l2count = 0, l3count = 0;while (!success){if (!(logical & 0x7fff)) level = 0;else if (!(logical & 0x3ff)) level = 1;else if (!(logical & 0x1f)) level = 2;else level = 3;if (!level) remapbase = ((physical - logical) >> 12) << 12;if (physical - logical - remapbase > 0x7fff || remapbase > 0xffff){printf("Need to remap across too high distance!\n");return 5;}int clean;for (clean = 0; clean < (1 << ((3 - level) * 5)) && physical + clean < sectors; clean++)if (!is_good(bitmap, physical + clean))break;if (clean >= 32768){bbt[64][(logical >> 15) << 1] = physical - logical - remapbase;bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;physical += 32768;logical += 32768;}else if (clean >= 1024){if (level == 0){if (bbtused == bbtpages) break;level = 1;l1 = bbt[bbtused];bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;bbtused++;l1count++;}l1[(logical >> 10) & 0x1f] = physical - logical - remapbase;physical += 1024;logical += 1024;}else if (clean >= 32){if (level == 0){if (bbtused == bbtpages) break;level = 1;l1 = bbt[bbtused];bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;bbtused++;l1count++;}if (level == 1){if (bbtused == bbtpages) break;level = 2;l2 = bbt[bbtused];l1[(logical >> 10) & 0x1f] = 0x8000 | (bbtused - 64);bbtused++;l2count++;}l2[(logical >> 5) & 0x1f] = physical - logical - remapbase;physical += 32;logical += 32;}else if (clean >= 1){if (level == 0){if (bbtused == bbtpages) break;level = 1;l1 = bbt[bbtused];bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;bbtused++;l1count++;}if (level == 1){if (bbtused == bbtpages) break;level = 2;l2 = bbt[bbtused];l1[(logical >> 10) & 0x1f] = 0x8000 | (bbtused - 64);bbtused++;l2count++;}if (level == 2){if (bbtused == bbtpages) break;level = 3;l3 = bbt[bbtused];l2[(logical >> 5) & 0x1f] = 0x8000 | (bbtused - 64);bbtused++;l3count++;}l3[logical & 0x1f] = physical - logical - remapbase;physical++;logical++;}else physical++;if (physical >= sectors) success = true;}if (success){printf("BBT using %d sectors (%d KiB)\n", bbtgood + 1, bbtsize >> 10);printf("Level 0: %d pages, Level 1: %d pages, Level 2: %d pages, Level 3: %d pages\n",l0count, l1count, l2count, l3count);printf("User data sectors: %d (%d KiB)\n", logical, logical << 2);memcpy(bbt, "emBIbbth", 8);((uint32_t*)bbt)[0x1fc] = logical;((uint32_t*)bbt)[0x1ff] = (bbtpages >> 6) - 1;break;}free(bbt);bbtpages += 64;}if (success){int out = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);if (out < 0){perror("Failed to open output file");return 3;}int rc;while (bbtsize && (rc = write(out, bbt, bbtsize)) >= 0) bbtsize -= rc;if (rc < 0){perror("Failed to open output file");return 4;}close(out);return 0;}printf("Can't fit BBT into 2052 KiB!\n");return 1;}