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);
36
    int l0count = (sectors + 0xfffff) >> 19;
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;
44
        bbt = malloc(bbtsize);
45
        memset(bbt, 0, bbtsize);
46
        int logical = 0;
47
        int physical = 1;
48
        int remapbase;
49
        int bbtgood;
50
        for (bbtgood = 0; bbtgood < (bbtpages >> 6) - 1; physical++)
51
            if (is_good(bitmap, physical))
52
            {
53
                ((uint32_t*)bbt)[0x200 + bbtgood] = physical;
54
                bbtgood++;
55
            }
56
        int bbtused = 64 + l0count;
57
        int level;
58
        uint16_t *l1, *l2, *l3;
59
        int l1count = 0, l2count = 0, l3count = 0;
60
        while (!success)
61
        {
62
            if (!(logical & 0x7fff)) level = 0;
63
            else if (!(logical & 0x3ff)) level = 1;
64
            else if (!(logical & 0x1f)) level = 2;
65
            else level = 3;
66
            if (!level) remapbase = ((physical - logical) >> 12) << 12;
67
            if (physical - logical - remapbase > 0x7fff || remapbase > 0xffff)
68
            {
69
                printf("Need to remap across too high distance!\n");
70
                return 5;
71
            }
72
            int clean;
73
            for (clean = 0; clean < (1 << ((3 - level) * 5)) && physical + clean < sectors; clean++)
74
                if (!is_good(bitmap, physical + clean))
75
                    break;
76
            if (clean >= 32768)
77
            {
78
                bbt[64][(logical >> 15) << 1] = physical - logical - remapbase;
79
                bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
80
                physical += 32768;
81
                logical += 32768;
82
            }
83
            else if (clean >= 1024)
84
            {
85
                if (level == 0)
86
                {
87
                    if (bbtused == bbtpages) break;
88
                    level = 1;
89
                    l1 = bbt[bbtused];
90
                    bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);
91
                    bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
92
                    bbtused++;
93
                    l1count++;
94
                }
95
                l1[(logical >> 10) & 0x1f] = physical - logical - remapbase;
96
                physical += 1024;
97
                logical += 1024;
98
            }
99
            else if (clean >= 32)
100
            {
101
                if (level == 0)
102
                {
103
                    if (bbtused == bbtpages) break;
104
                    level = 1;
105
                    l1 = bbt[bbtused];
106
                    bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);
107
                    bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
108
                    bbtused++;
109
                    l1count++;
110
                }
111
                if (level == 1)
112
                {
113
                    if (bbtused == bbtpages) break;
114
                    level = 2;
115
                    l2 = bbt[bbtused];
116
                    l1[(logical >> 10) & 0x1f] = 0x8000 | (bbtused - 64);
117
                    bbtused++;
118
                    l2count++;
119
                }
120
                l2[(logical >> 5) & 0x1f] = physical - logical - remapbase;
121
                physical += 32;
122
                logical += 32;
123
            }
124
            else if (clean >= 1)
125
            {
126
                if (level == 0)
127
                {
128
                    if (bbtused == bbtpages) break;
129
                    level = 1;
130
                    l1 = bbt[bbtused];
131
                    bbt[64][(logical >> 15) << 1] = 0x8000 | (bbtused - 64);
132
                    bbt[64][((logical >> 15) << 1) | 1] = remapbase >> 12;
133
                    bbtused++;
134
                    l1count++;
135
                }
136
                if (level == 1)
137
                {
138
                    if (bbtused == bbtpages) break;
139
                    level = 2;
140
                    l2 = bbt[bbtused];
141
                    l1[(logical >> 10) & 0x1f] = 0x8000 | (bbtused - 64);
142
                    bbtused++;
143
                    l2count++;
144
                }
145
                if (level == 2)
146
                {
147
                    if (bbtused == bbtpages) break;
148
                    level = 3;
149
                    l3 = bbt[bbtused];
150
                    l2[(logical >> 5) & 0x1f] = 0x8000 | (bbtused - 64);
151
                    bbtused++;
152
                    l3count++;
153
                }
154
                l3[logical & 0x1f] = physical - logical - remapbase;
155
                physical++;
156
                logical++;
157
            }
158
            else physical++;
159
            if (physical >= sectors) success = true;
160
        }
161
        if (success)
162
        {        
163
            printf("BBT using %d sectors (%d KiB)\n", bbtgood + 1, bbtsize >> 10);
164
            printf("Level 0: %d pages, Level 1: %d pages, Level 2: %d pages, Level 3: %d pages\n",
165
                   l0count, l1count, l2count, l3count);
166
            printf("User data sectors: %d (%d KiB)\n", logical, logical << 2);
167
            memcpy(bbt, "emBIbbth", 8);
339 theseven 168
            ((uint32_t*)bbt)[0x1fc] = logical;
337 theseven 169
            ((uint32_t*)bbt)[0x1ff] = (bbtpages >> 6) - 1;
170
            break;
171
        }
172
        free(bbt);
173
        bbtpages += 64;
174
    }
175
    if (success)
176
    {
177
        int out = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
178
        if (out < 0)
179
        {
180
            perror("Failed to open output file");
181
            return 3;
182
        }
183
        int rc;
184
        while (bbtsize && (rc = write(out, bbt, bbtsize)) >= 0) bbtsize -= rc;
185
        if (rc < 0)
186
        {
187
            perror("Failed to open output file");
188
            return 4;
189
        }
190
        close(out);
191
        return 0;
192
    }
193
    printf("Can't fit BBT into 2052 KiB!\n");
194
    return 1;
195
}