Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emBIOS is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "storage.h"
26
#include "fat32.h"
27
#include "util.h"
28
 
29
 
30
uint32_t fat32_ok;
31
uint32_t fat32_startsector;
32
uint32_t fat32_secperclus;
33
uint32_t fat32_database;
34
uint32_t fat32_fatbase;
35
uint32_t fat32_fatsize;
36
uint32_t fat32_fatcount;
37
uint32_t fat32_sectorcount;
38
uint32_t fat32_clustercount;
39
uint32_t fat32_rootdirclus;
40
uint32_t fat32_buf1[0x200] __attribute__((aligned(16)));
41
uint32_t fat32_buf2[0x200] __attribute__((aligned(16)));
42
 
43
 
44
uint32_t fat32_get_root()
45
{
46
    return fat32_rootdirclus;
47
}
48
 
49
uint32_t fat32_get_clusterchain(uint32_t clusterchain, uint32_t maxsize, void* buffer)
50
{
51
    uint32_t i;
52
    for (i = 0; i < (maxsize >> 11); )
53
    {
54
        uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
55
        uint32_t count = fat32_secperclus;
56
        if (count + i > (maxsize >> 11)) count = (maxsize >> 11) - i;
57
        uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
58
        if (storage_read(fatsector, 1, &((uint32_t*)buffer)[i << 9])) return 1;
59
        clusterchain = ((uint32_t*)buffer)[(i << 9) + (clusterchain & 0x1FF)];
60
        if (storage_read(sector, count, &((uint32_t*)buffer)[i << 9])) return 1;
61
        i += count;
62
        if (clusterchain >= 0x0ffffff0) return 0;
63
    }
64
    return clusterchain;
65
}
66
 
67
uint32_t fat32_get_direntry(uint32_t clusterchain, const char* filename, uint32_t* filesize)
68
{
69
    uint32_t i, j;
70
    while (clusterchain > 1 && clusterchain < 0x0ffffff0)
71
    {
72
        uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
73
        for (j = 0; j < fat32_secperclus; j++)
74
        {
75
            if (storage_read(sector + j, 1, fat32_buf1)) return 1;
76
            for (i = 0; i < 0x200; i += 8)
77
                if (((uint8_t*)fat32_buf1)[i << 2] == 0) return 0;
78
                else if (((uint8_t*)fat32_buf1)[i << 2] == 0xe5) continue;
79
                else if (memcmp(&fat32_buf1[i], filename, 11) == 0)
80
                {
81
                    *filesize = fat32_buf1[i + 7];
82
                    return (((uint16_t*)fat32_buf1)[(i << 1) + 0xA] << 16)
83
                         | ((uint16_t*)fat32_buf1)[(i << 1) + 0xD];
84
                }
85
        }
86
        uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
87
        if (storage_read(fatsector, 1, fat32_buf1)) return 1;
88
        clusterchain = fat32_buf1[(i << 9) + (clusterchain & 0x1FF)];
89
    }
90
    return 0;
91
}
92
 
93
uint32_t fat32_delete_clusterchain(uint32_t clusterchain)
94
{
95
    while (1)
96
    {
97
        uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
98
        if (storage_read(fatsector, 1, fat32_buf1)) return 1;
99
        clusterchain = fat32_buf1[clusterchain & 0x1FF];
100
        fat32_buf1[(clusterchain & 0x1FF)] = 0;
101
        if (storage_write(fatsector, 1, fat32_buf1)) return 1;
102
        if (clusterchain >= 0x0ffffff0) return 0;
103
    }
104
}
105
 
106
uint32_t fat32_delete_direntry(uint32_t clusterchain, const char* filename)
107
{
108
    uint32_t i, j;
109
    while (clusterchain > 1 && clusterchain < 0x0ffffff0)
110
    {
111
        uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
112
        for (j = 0; j < fat32_secperclus; j++)
113
        {
114
            if (storage_read(sector + j, 1, fat32_buf1)) return 1;
115
            for (i = 0; i < 0x200; i += 8)
116
                if (((uint8_t*)fat32_buf1)[i << 2] == 0) return 0;
117
                else if (((uint8_t*)fat32_buf1)[i << 2] == 0xe5) continue;
118
                else if (memcmp(&fat32_buf1[i], filename, 11) == 0)
119
                {
120
                    ((uint8_t*)fat32_buf1)[i << 2] = 0xe5;
121
                    if (storage_write(sector + j, 1, fat32_buf1)) return 1;
122
                    return 0;
123
                }
124
        }
125
        uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
126
        if (storage_read(fatsector, 1, fat32_buf1)) return 1;
127
        clusterchain = fat32_buf1[(i << 9) + (clusterchain & 0x1FF)];
128
    }
129
    return 0;
130
}
131
 
132
uint32_t fat32_store_stream(void* buffer, uint32_t size)
133
{
134
    uint32_t i;
135
    uint32_t clusterchain = 0;
136
    uint32_t scanidx = 2;
137
    uint32_t scansect = 0xffffffff;
138
    uint32_t lastidx;
139
    uint32_t lastsect = 0xffffffff;
140
    uint32_t dirty = 0;
141
    while (size)
142
    {
143
        while (scanidx < fat32_clustercount + 2)
144
        {
145
            if ((scanidx >> 9) != scansect)
146
            {
147
                scansect = scanidx >> 9;
148
                if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
149
            }
150
            if (!fat32_buf1[scanidx & 0x1ff]) break;
151
            scanidx++;
152
        }
153
        if (scanidx >= fat32_clustercount + 2) return 0;
154
        if (!clusterchain) clusterchain = scanidx;
155
        else
156
        {
157
            fat32_buf2[lastidx & 0x1ff] = scanidx;
158
            dirty = 1;
159
        }
160
        lastidx = scanidx;
161
        if ((lastidx >> 9) != lastsect)
162
        {
163
            if (dirty)
164
                if (storage_write(fat32_fatbase + lastsect, 1, fat32_buf2)) return 0;
165
            dirty = 0;
166
            lastsect = lastidx >> 9;
167
            memcpy(fat32_buf2, fat32_buf1, 0x800);
168
        }
169
        uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
170
        uint32_t count = (size + 0x7ff) >> 11;
171
        if (count > fat32_secperclus) count = fat32_secperclus;
172
        if (storage_write(sector, count, &((uint32_t*)buffer)[i << 9])) return 0;
173
        if ((count << 11) >= size)
174
        {
175
            fat32_buf2[lastidx & 0x1ff] = 0x0fffffff;
176
            if (storage_write(fat32_fatbase + lastsect, 1, fat32_buf2)) return 0;
177
            break;
178
        }
179
        size -= count << 11;
180
        buffer = (void*)((uint32_t)buffer + (count << 11));
181
        scanidx++;
182
    }
183
    return clusterchain;
184
}
185
 
186
void fat32_set_direntry(uint32_t* ptr, const char* filename, uint32_t filechain,
187
                        uint32_t filesize, uint32_t flags)
188
{
189
    memcpy(ptr, filename, 11);
190
    ((uint16_t*)ptr)[0xa] = filechain >> 16;
191
    ((uint8_t*)ptr)[0xb] = flags;
192
    ((uint16_t*)ptr)[0xa] = filechain >> 16;
193
    ((uint16_t*)ptr)[0xd] = filechain & 0xffff;
194
    ptr[7] = filesize;
195
}
196
 
197
uint32_t fat32_store_direntry(uint32_t dirchain, const char* filename,
198
                              uint32_t filechain, uint32_t filesize, uint32_t flags)
199
{
200
    uint32_t i, j;
201
    uint32_t lastidx;
202
    while (dirchain > 1 && dirchain < 0x0ffffff0)
203
    {
204
        uint32_t sector = (dirchain - 2) * fat32_secperclus + fat32_database;
205
        for (j = 0; j < fat32_secperclus; j++)
206
        {
207
            if (storage_read(sector + j, 1, fat32_buf1)) return 1;
208
            for (i = 0; i < 0x200; i += 8)
209
                if (((uint8_t*)fat32_buf1)[i << 2] == 0
210
                 || ((uint8_t*)fat32_buf1)[i << 2] == 0xe5)
211
                {
212
                    fat32_set_direntry(&fat32_buf1[i], filename, filechain, filesize, flags);
213
                    if (storage_write(sector + j, 1, fat32_buf1)) return 1;
214
                    return 0;
215
                }
216
        }
217
        uint32_t fatsector = fat32_fatbase + (dirchain >> 9);
218
        if (storage_read(fatsector, 1, fat32_buf1)) return 1;
219
        lastidx = dirchain;
220
        dirchain = fat32_buf1[(i << 9) + (dirchain & 0x1FF)];
221
    }
222
    uint32_t scanidx = 2;
223
    uint32_t scansect = 0xffffffff;
224
    while (scanidx < fat32_clustercount + 2)
225
    {
226
        if ((scanidx >> 9) != scansect)
227
        {
228
            scansect = scanidx >> 9;
229
            if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
230
        }
231
        if (!fat32_buf1[scanidx & 0x1ff]) break;
232
        scanidx++;
233
    }
234
    if (scanidx >= fat32_clustercount + 2) return 1;
235
    fat32_buf1[scanidx & 0x1ff] = 0x0fffffff;
236
    if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
237
    if (storage_read(fat32_fatbase + (lastidx >> 9), 1, fat32_buf1)) return 1;
238
    fat32_buf1[lastidx & 0x1ff] = scanidx;
239
    if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
240
    uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
241
    for (i = 0; i < fat32_secperclus; i++)
242
    {
243
        memset(fat32_buf1, 0, 0x800);
244
        if (!i) fat32_set_direntry(fat32_buf1, filename, filechain, filesize, flags);
245
        if (storage_write(sector + i, 1, fat32_buf1)) return 1;
246
    }
247
    return 0;
248
}
249
 
250
uint32_t fat32_create_dir(uint32_t parent, const char* dirname)
251
{
252
    uint32_t i;
253
    uint32_t scanidx = 2;
254
    uint32_t scansect = 0xffffffff;
255
    while (scanidx < fat32_clustercount + 2)
256
    {
257
        if ((scanidx >> 9) != scansect)
258
        {
259
            scansect = scanidx >> 9;
260
            if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
261
        }
262
        if (!fat32_buf1[scanidx & 0x1ff]) break;
263
        scanidx++;
264
    }
265
    if (scanidx >= fat32_clustercount + 2) return 0;
266
    fat32_buf1[scanidx & 0x1ff] = 0x0fffffff;
267
    if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
268
    fat32_store_direntry(parent, dirname, scanidx, 0, 0x10);
269
    uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
270
    for (i = 0; i < fat32_secperclus; i++)
271
    {
272
        memset(fat32_buf1, 0, 0x800);
273
        if (!i)
274
        {
275
            fat32_set_direntry(fat32_buf1, ".          ", scanidx, 0, 0x10);
276
            if (parent == fat32_rootdirclus) parent = 0;
277
            fat32_set_direntry(&fat32_buf1[8], "..         ", parent, 0, 0x10);
278
        }
279
        if (storage_write(sector + i, 1, fat32_buf1)) return 0;
280
    }
281
    return scanidx;
282
}
283
 
284
uint32_t fat32_read_file(const char* filename, uint32_t maxsize, void* buffer, uint32_t* filesize)
285
{
286
}
287
 
288
uint32_t fat32_get_partition_start()
289
{
290
    return fat32_startsector;
291
}
292
 
293
uint32_t fat32_init()
294
{
295
    uint32_t i;
296
    fat32_ok = 0;
297
    fat32_startsector = 0xFFFFFFFF;
298
    if (storage_init()) return 1;
299
 
300
    if (storage_read(0, 1, fat32_buf1)) return 1;
301
 
302
    if (*((uint16_t*)((uint32_t)fat32_buf1 + 0x1FE)) != 0xAA55)
303
    {
304
        return 1;
305
    }
306
 
307
    for (i = 0x1C2; i < 0x200; i += 0x10)
308
        if (((uint8_t*)fat32_buf1)[i] == 0xB)
309
        {
310
            fat32_startsector = *((uint16_t*)((uint32_t)fat32_buf1 + i + 4))
311
                              | (*((uint16_t*)((uint32_t)fat32_buf1 + i + 6)) << 16);
312
            break;
313
        }
314
 
315
    if (fat32_startsector == 0xFFFFFFFF
316
     && *((uint16_t*)((uint32_t)fat32_buf1 + 0x52)) == 0x4146
317
     && *((uint8_t*)((uint32_t)fat32_buf1 + 0x54)) == 0x54)
318
        fat32_startsector = 0;
319
 
320
    if (fat32_startsector == 0xFFFFFFFF) return 1;
321
 
322
    if (storage_read(fat32_startsector, 1, fat32_buf1)) return 1;
323
 
324
    if (*((uint16_t*)((uint32_t)fat32_buf1 + 0x1FE)) != 0xAA55) return 1;
325
 
326
    if (((uint8_t*)fat32_buf1)[0xB] != 0 || ((uint8_t*)fat32_buf1)[0xC] != 8) return 1;
327
 
328
    fat32_secperclus = ((uint8_t*)fat32_buf1)[0xD];
329
    uint32_t reserved = ((uint16_t*)fat32_buf1)[0x7];
330
    fat32_fatcount = ((uint8_t*)fat32_buf1)[0x10];
331
 
332
    if (((uint8_t*)fat32_buf1)[0x11] != 0) return 1;
333
 
334
    fat32_sectorcount = fat32_buf1[8];
335
    fat32_fatsize = fat32_buf1[9];
336
 
337
    if (((uint16_t*)fat32_buf1)[0x15] != 0) return 1;
338
 
339
    fat32_rootdirclus = fat32_buf1[0xB];
340
 
341
    fat32_clustercount = (fat32_sectorcount - reserved
342
                        - fat32_fatcount * fat32_fatsize) / fat32_secperclus;
343
 
344
    fat32_fatbase = fat32_startsector + reserved;
345
    fat32_database = fat32_fatbase + fat32_fatcount * fat32_fatsize;
346
 
347
    fat32_ok = 1;
348
    return 0;
349
}