Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
337 theseven 1
#include <stdio.h> 
2
#include <stdint.h>
3
#include <stdbool.h>
4
#include <fcntl.h>
5
 
6
static void mark_bad(uint32_t* bitmap, int sector)
7
{
8
    bitmap[sector >> 5] &= ~(1 << (sector & 31));
9
}
10
 
11
static bool is_good(uint32_t* bitmap, int sector)
12
{
13
    return bitmap[sector >> 5] & (1 << (sector & 31));
14
}
15
 
16
int main(int argc, char** argv)
17
{
18
    int sectors;
19
    sscanf(argv[3], "%i", &sectors);
20
    size_t bitmapsize = ((sectors + 65535) & ~0xffff) >> 3;
21
    uint32_t* bitmap = malloc(bitmapsize);
22
    memset(bitmap, 0xff, bitmapsize);
23
    FILE* in = fopen(argv[1], "r");
24
    if (!in)
25
    {
26
        perror("Failed to open input file");
27
        return 2;
28
    }
29
    char line[256];
30
    while (fgets(line, sizeof(line), in))
31
    {
32
        int sector;
33
        if (sscanf(line, "%i", &sector) == 1 && sector) mark_bad(bitmap, sector);
34
    }
35
    fclose(in);
603 theseven 36
    int l0count = (sectors + 0x7ffff) >> 19;
337 theseven 37
    int bbtpages = 64 + ((l0count + 0x3f) & ~0x3f);
38
    int bbtsize;
39
    uint16_t (*bbt)[0x20];
40
    bool success = false;
41
    while (bbtpages <= 32832)
42
    {
43
        bbtsize = bbtpages << 6;
618 theseven 44
        l0count = (sectors - bbtsize + 0xfffff) >> 19;
337 theseven 45
        bbt = malloc(bbtsize);
46
        memset(bbt, 0, bbtsize);
47
        int logical = 0;
48
        int physical = 1;
49
        int remapbase;
50
        int bbtgood;
51
        for (bbtgood = 0; bbtgood < (bbtpages >> 6) - 1; physical++)
52
            if (is_good(bitmap, physical))
53
            {
54
                ((uint32_t*)bbt)[0x200 + bbtgood] = physical;
55
                bbtgood++;
56
            }
57
        int bbtused = 64 + l0count;
58
        int level;
59
        uint16_t *l1, *l2, *l3;
60
        int l1count = 0, l2count = 0, l3count = 0;
61
        while (!success)
62
        {
63
            if (!(logical & 0x7fff)) level = 0;
64
            else if (!(logical & 0x3ff)) level = 1;
65
            else if (!(logical & 0x1f)) level = 2;
66
            else level = 3;
67
            if (!level) remapbase = ((physical - logical) >> 12) << 12;
68
            if (physical - logical - remapbase > 0x7fff || remapbase > 0xffff)
69
            {
70
                printf("Need to remap across too high distance!\n");
71
                return 5;
72
            }
73
            int clean;
74
            for (clean = 0; clean < (1 << ((3 - level) * 5)) && physical + clean < sectors; clean++)
75
                if (!is_good(bitmap, physical + clean))
76
                    break;
77
            if (clean >= 32768)
78
            {
79
                bbt[64][(logical >> 15) << 1] = physical - logical - remapbase;
80
                bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
81
                physical += 32768;
82
                logical += 32768;
83
            }
84
            else if (clean >= 1024)
85
            {
86
                if (level == 0)
87
                {
88
                    if (bbtused == bbtpages) break;
89
                    level = 1;
90
                    l1 = bbt[bbtused];
91
                    bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);
92
                    bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
93
                    bbtused++;
94
                    l1count++;
95
                }
96
                l1[(logical >> 10) & 0x1f] = physical - logical - remapbase;
97
                physical += 1024;
98
                logical += 1024;
99
            }
100
            else if (clean >= 32)
101
            {
102
                if (level == 0)
103
                {
104
                    if (bbtused == bbtpages) break;
105
                    level = 1;
106
                    l1 = bbt[bbtused];
107
                    bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);
108
                    bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
109
                    bbtused++;
110
                    l1count++;
111
                }
112
                if (level == 1)
113
                {
114
                    if (bbtused == bbtpages) break;
115
                    level = 2;
116
                    l2 = bbt[bbtused];
117
                    l1[(logical >> 10) & 0x1f] = 0x8000 | (bbtused - 64);
118
                    bbtused++;
119
                    l2count++;
120
                }
121
                l2[(logical >> 5) & 0x1f] = physical - logical - remapbase;
122
                physical += 32;
123
                logical += 32;
124
            }
125
            else if (clean >= 1)
126
            {
127
                if (level == 0)
128
                {
129
                    if (bbtused == bbtpages) break;
130
                    level = 1;
131
                    l1 = bbt[bbtused];
132
                    bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);
133
                    bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
134
                    bbtused++;
135
                    l1count++;
136
                }
137
                if (level == 1)
138
                {
139
                    if (bbtused == bbtpages) break;
140
                    level = 2;
141
                    l2 = bbt[bbtused];
142
                    l1[(logical >> 10) & 0x1f] = 0x8000 | (bbtused - 64);
143
                    bbtused++;
144
                    l2count++;
145
                }
146
                if (level == 2)
147
                {
148
                    if (bbtused == bbtpages) break;
149
                    level = 3;
150
                    l3 = bbt[bbtused];
151
                    l2[(logical >> 5) & 0x1f] = 0x8000 | (bbtused - 64);
152
                    bbtused++;
153
                    l3count++;
154
                }
155
                l3[logical & 0x1f] = physical - logical - remapbase;
156
                physical++;
157
                logical++;
158
            }
159
            else physical++;
160
            if (physical >= sectors) success = true;
161
        }
162
        if (success)
163
        {        
164
            printf("BBT using %d sectors (%d KiB)\n", bbtgood + 1, bbtsize >> 10);
165
            printf("Level 0: %d pages, Level 1: %d pages, Level 2: %d pages, Level 3: %d pages\n",
166
                   l0count, l1count, l2count, l3count);
167
            printf("User data sectors: %d (%d KiB)\n", logical, logical << 2);
168
            memcpy(bbt, "emBIbbth", 8);
339 theseven 169
            ((uint32_t*)bbt)[0x1fc] = logical;
337 theseven 170
            ((uint32_t*)bbt)[0x1ff] = (bbtpages >> 6) - 1;
171
            break;
172
        }
173
        free(bbt);
174
        bbtpages += 64;
175
    }
176
    if (success)
177
    {
178
        int out = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
179
        if (out < 0)
180
        {
181
            perror("Failed to open output file");
182
            return 3;
183
        }
184
        int rc;
185
        while (bbtsize && (rc = write(out, bbt, bbtsize)) >= 0) bbtsize -= rc;
186
        if (rc < 0)
187
        {
188
            perror("Failed to open output file");
189
            return 4;
190
        }
191
        close(out);
192
        return 0;
193
    }
194
    printf("Can't fit BBT into 2052 KiB!\n");
195
    return 1;
196
}