Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
366 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 "embiosapp.h"
25
 
26
 
27
void main();
28
EMBIOS_APP_HEADER("Installer thread", 0x10000, main, 127)
29
 
30
 
31
uint16_t lcdbuffer[320 * 240];
32
#define BMPIDX_SIDEPANE 0
33
#define BMPIDX_WARNING 1
34
#define BMPIDX_INSTALLING 2
35
#define BMPIDX_FORMATTING 3
36
#define BMPIDX_COPYING 4
37
#define BMPIDX_FLASHING 5
38
 
39
struct wakeup eventwakeup;
40
volatile int button;
41
 
42
char mallocbuf[0xea0000] __attribute__((aligned(16)));
43
tlsf_pool mallocpool;
44
 
45
extern uint32_t _scriptstart;
46
 
47
 
48
#define SHA1CONFIG    (*((volatile uint32_t*)(0x38000000)))
49
#define SHA1RESET     (*((volatile uint32_t*)(0x38000004)))
50
#define SHA1RESULT      ((volatile uint32_t*)(0x38000020))
51
#define SHA1DATAIN      ((volatile uint32_t*)(0x38000040))
52
 
53
void sha1(void* data, uint32_t size, void* hash)
54
{
55
    int i, space;
56
    bool done = false;
57
    uint32_t tmp32[16];
58
    uint8_t* tmp8 = (uint8_t*)tmp32;
59
    uint32_t* databuf = (uint32_t*)data;
60
    uint32_t* hashbuf = (uint32_t*)hash;
61
    clockgate_enable(0, true);
62
    SHA1RESET = 1;
63
    while (SHA1CONFIG & 1) sleep(0);
64
    SHA1RESET = 0;
65
    SHA1CONFIG = 0;
66
    while (!done)
67
    {
68
        space = ((uint32_t)databuf) - ((uint32_t)data) - size + 64;
69
        if (space > 0)
70
        {
71
            for (i = 0; i < 16; i++) tmp32[i] = 0;
72
            if (space <= 64)
73
            {
74
                for (i = 0; i < 64 - space; i++) tmp8[i] = ((uint8_t*)databuf)[i];
75
                tmp8[64 - space] = 0x80;
76
            }
77
            if (space >= 8)
78
            {
79
                tmp8[0x3b] = (size >> 29) & 0xff;
80
                tmp8[0x3c] = (size >> 21) & 0xff;
81
                tmp8[0x3d] = (size >> 13) & 0xff;
82
                tmp8[0x3e] = (size >> 5) & 0xff;
83
                tmp8[0x3f] = (size << 3) & 0xff;
84
                done = true;
85
            }
86
            for (i = 0; i < 16; i++) SHA1DATAIN[i] = tmp32[i];
87
        }
88
        else for (i = 0; i < 16; i++) SHA1DATAIN[i] = databuf[i];
89
        databuf += 16;
90
        SHA1CONFIG |= 2;
91
        while (SHA1CONFIG & 1) sleep(0);
92
        SHA1CONFIG |= 8;
93
    }
94
    for (i = 0; i < 5; i++) hashbuf[i] = SHA1RESULT[i];
95
    clockgate_enable(0, false);
96
}
97
 
98
 
99
void handler(enum button_event eventtype, int which, int value)
100
{
101
    if (eventtype == BUTTON_PRESS) button |= 1 << which;
102
    wakeup_signal(&eventwakeup);
103
}
104
 
105
void* malloc(size_t size)
106
{
107
    void* result = tlsf_malloc(mallocpool, size);
108
    if (!result && size) panic(PANIC_KILLTHREAD, "Out of memory!");
109
    return result;
110
}
111
 
112
void* memalign(size_t align, size_t size)
113
{
114
    void* result = tlsf_memalign(mallocpool, align, size);
115
    if (!result && size) panic(PANIC_KILLTHREAD, "Out of memory!");
116
    return result;
117
}
118
 
119
void* realloc(void* ptr, size_t size)
120
{
121
    void* result = tlsf_realloc(mallocpool, ptr, size);
122
    if (!result && size) panic(PANIC_KILLTHREAD, "Out of memory!");
123
    return result;
124
}
125
 
126
void free(void* ptr)
127
{
128
    tlsf_free(mallocpool, ptr);
129
}
130
 
131
uint32_t freeret(uint32_t rc, void* ptr)
132
{
133
    tlsf_free(mallocpool, ptr);
134
    return rc;
135
}
136
 
137
void mkfat32(struct progressbar_state* progressbar)
138
{
139
    uint32_t i, j, rc;
140
    uint32_t rootdirclus = 2;
141
    uint32_t secperclus = 1;
142
    uint32_t fatsectors = 1;
143
    uint32_t oldfatsectors = 0;
144
    uint32_t clustercount;
145
    uint32_t reserved = 2;
146
    struct storage_info storageinfo;
147
    storage_get_info(0, &storageinfo);
148
    uint32_t totalsectors = storageinfo.num_sectors;
149
    disk_unmount(0);
150
    while (fatsectors != oldfatsectors)
151
    {
152
        oldfatsectors = fatsectors;
153
        clustercount = (totalsectors - fatsectors - reserved) / secperclus;
154
        fatsectors = (clustercount + 1025) >> 10;
155
    }
156
    uint32_t database = fatsectors + reserved;
157
    uint32_t clusoffset = 0;
158
    uint32_t* buf = memalign(0x20000, 0x10);
159
    memset(buf, 0, 0x800);
160
    memcpy(buf, "\xeb\x58\x00MSWIN5.0\0\x10", 0xd);
161
    ((uint8_t*)buf)[0xd] = secperclus;
162
    ((uint16_t*)buf)[7] = reserved;
163
    memcpy(&((uint8_t*)buf)[0x10], "\x01\0\0\0\0\xf8\0\0\x3f\0\xff", 0xb);
164
    buf[8] = totalsectors;
165
    buf[9] = fatsectors;
166
    buf[0xb] = rootdirclus + clusoffset;
167
    ((uint16_t*)buf)[0x18] = 1;
168
    ((uint8_t*)buf)[0x40] = 0x80;
169
    ((uint8_t*)buf)[0x42] = 0x29;
170
    memcpy(&((uint8_t*)buf)[0x43], "\0\0\0\0iPodClassic", 0xf);
171
    memcpy(&((uint8_t*)buf)[0x52], "FAT32   ", 8);
172
    ((uint16_t*)buf)[0xff] = 0xaa55;
173
    if (rc = storage_write_sectors_md(0, 0, 1, buf))
174
        panicf(PANIC_KILLTHREAD, "Error writing MBR: %08X", rc);
175
    memset(buf, 0, 0x800);
176
    buf[0] = 0x41615252;
177
    buf[0x79] = 0x61417272;
178
    buf[0x7a] = clustercount - 1;
179
    buf[0x7b] = 2;
180
    buf[0x7f] = 0xaa550000;
181
    if (rc = storage_write_sectors_md(0, 1, 1, buf))
182
        panicf(PANIC_KILLTHREAD, "Error writing FSINFO: %08X", rc);
183
    progressbar_init(progressbar, 5, 189, 65, 80, 0, 0xdefb, 0x1d, 0, fatsectors);
184
    uint32_t cursect = 0;
185
    for (i = 0; i < fatsectors; i += 32)
186
    {
187
        memset(buf, 0, 0x20000);
188
        if (!i) memcpy(buf, "\xf8\xff\xff\x0f\xff\xff\xff\xff\xff\xff\xff\x0f", 12);
189
        if (rc = storage_write_sectors_md(0, reserved + i, MIN(fatsectors - i, 32), buf))
190
            panicf(PANIC_KILLTHREAD, "Error writing FAT sectors %d-%d: %08X", i, MIN(fatsectors - 1, i + 31), rc);
191
        progressbar_setpos(progressbar, i, false);
192
    }
193
    memset(buf, 0, secperclus * 0x1000);
194
    memcpy(buf, "iPodClassic\x08", 12);
195
    if (rc = storage_write_sectors_md(0, database, secperclus, buf))
196
        panicf(PANIC_KILLTHREAD, "Error writing root directory sectors: %08X", i, rc);
197
    free(buf);
198
    disk_mount(0);
199
}
200
 
201
void main(void)
202
{
203
    uint32_t i, j, k, rc;
204
    void* bitmapdata[6];
205
    uint32_t bitmapsize[6];
206
    uint32_t* script;
207
#define scriptb ((uint8_t*)script)
208
    uint32_t dummy;
209
    struct progressbar_state progressbar;
210
    bool appleflash;
211
    void* syscfgptr;
212
    uint8_t* norbuf;
213
#define norbufword ((uint32_t*)norbuf)
214
    uint8_t* oldnor;
215
#define oldnorword ((uint32_t*)oldnor)
216
 
217
    button = 0;
218
    wakeup_init(&eventwakeup);
219
    button_register_handler(handler);
220
    mallocpool = tlsf_create(mallocbuf, sizeof(mallocbuf));
221
 
222
    script = &_scriptstart;
223
    for (i = 0; i < 6; i++)
224
    {
225
        bitmapsize[i] = *script;
226
        bitmapdata[i] = &script[1];
227
        script = &script[1 + (bitmapsize[i] >> 2)];
228
    }
229
 
230
    void* bmpbuffer = malloc(0x25900);
231
    memset(lcdbuffer, 0xff, 0x25800);
232
    ucl_decompress(bitmapdata[BMPIDX_SIDEPANE], bitmapsize[BMPIDX_SIDEPANE], bmpbuffer, &dummy);
233
    renderbmp(&lcdbuffer[195], bmpbuffer, 320);
234
    int updating = mkdir("/iLoader");
235
    if (!updating)
236
    {
237
        ucl_decompress(bitmapdata[BMPIDX_WARNING], bitmapsize[BMPIDX_WARNING], bmpbuffer, &dummy);
238
        renderbmp(lcdbuffer, bmpbuffer, 320);
239
        displaylcd(0, 319, 0, 239, lcdbuffer, 0);
240
    }
241
    else
242
    {
243
        ucl_decompress(bitmapdata[BMPIDX_INSTALLING], bitmapsize[BMPIDX_INSTALLING],
244
                       bmpbuffer, &dummy);
245
        renderbmp(lcdbuffer, bmpbuffer, 320);
246
    }
247
    backlight_set_fade(32);
248
    backlight_set_brightness(177);
249
    backlight_on(true);
250
 
251
 
252
    oldnor = memalign(0x100000, 0x10);
253
    norbuf = memalign(0x100000, 0x10);
254
    bootflash_readraw(oldnor, 0, 0x100000);
255
    memset(norbuf, 0xff, 0x100000);
256
    if (oldnorword[0x400] == 0x53436667) appleflash = false;
257
    else
258
    {
259
        if (oldnorword[0x1000] == 0x53436667) appleflash = true;
260
        else panic(PANIC_KILLTHREAD, "Boot flash contents are damaged! "
261
                                     "(No SYSCFG found)\n\nPlease ask for help.\n");
262
    }
263
    if (appleflash) memcpy(&norbuf[0x1000], &oldnor[0x4000], 0x1000);
264
    else memcpy(&norbuf[0x1000], &oldnor[0x1000], 0x1000);
265
    uint32_t sp = 0;
266
    uint32_t beginptr = 0x2000;
267
    uint32_t endptr = 0x100000;
268
    uint32_t dirptr = 0;
269
    while (script[sp])
270
    {
271
        uint32_t file = script[sp] & 0xff;
272
        uint32_t flags = (script[sp] >> 8) & 0xff;
273
        uint32_t align = (script[sp] >> 16) & 0xff;
274
        void* data;
275
        uint32_t size;
276
        sp++;
277
        switch (file)
278
        {
279
            default:
280
                data = &scriptb[script[sp++]];
281
                size = script[sp++];
282
        }
283
        if (size)
284
        {
285
            if (align && !(flags & 1))
286
            {
287
                if ((align << 12) < beginptr)
288
                    panicf(PANIC_KILLTHREAD, "Error: Align failed! (%02X)", align);
289
                beginptr = align << 12;
290
            }
291
            if (endptr - beginptr < size)
292
                panicf(PANIC_KILLTHREAD, "Error: Flash is full!");
293
            uint32_t storesize = size;
294
            if (flags & 2) storesize |= 0x80000000;
295
            int offs = 0;
296
            if (flags & 8)
297
            {
298
                offs = 0x800;
299
                size = ((size + 0xf) & ~0xf) + offs;
300
            }
301
            if (flags & 1)
302
            {
303
                endptr -= ((size + 0xfff) & ~0xfff);
304
                memcpy(&norbuf[endptr + offs], data, size);
305
                file = endptr;
306
            }
307
            else
308
            {
309
                memcpy(&norbuf[beginptr + offs], data, size);
310
                file = beginptr;
311
                beginptr += ((size + 0xfff) & ~0xfff);
312
            }
313
            if (!(flags & 4))
314
            {
315
                if (dirptr >= 0x1000)
316
                    panicf(PANIC_KILLTHREAD, "Error: Directory is full!");
317
                memcpy(&norbuf[dirptr], &script[sp], 8);
318
                norbufword[(dirptr >> 2) + 2] = file;
319
                norbufword[(dirptr >> 2) + 3] = storesize;
320
                dirptr += 0x10;
321
                sp += 2;
322
            }
323
            if (flags & 8)
324
            {
325
                size -= offs;
326
                memset(&norbuf[file], 0, 0x800);
327
                memcpy(&norbuf[file], "87021.0\x01", 8);
328
                *((uint32_t*)&norbuf[file + 0xc]) = size;
329
                sha1(&norbuf[file + 0x800], size, &norbuf[file + 0x10]);
330
                *((uint32_t*)&norbuf[file + 0x20]) = 0;
331
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x10], 0x10);
332
                sha1(&norbuf[file], 0x40, &norbuf[file + 0x40]);
333
                *((uint32_t*)&norbuf[file + 0x50]) = 0;
334
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x40], 0x10);
335
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x800], size);
336
            }
337
        }
338
        else if (!(flags & 4)) sp += 2;
339
    }
340
 
341
    if (!updating)
342
    {
343
        while (true)
344
        {
345
            wakeup_wait(&eventwakeup, TIMEOUT_BLOCK);
346
            if (button == 2) break;
347
            else if (button == 4)
348
            {
349
                shutdown(true);
350
                reset();
351
            }
352
            button = 0;
353
        }
354
        memset(lcdbuffer, 0xff, 0x25800);
355
        ucl_decompress(bitmapdata[BMPIDX_SIDEPANE], bitmapsize[BMPIDX_SIDEPANE], bmpbuffer, &dummy);
356
        renderbmp(&lcdbuffer[195], bmpbuffer, 320);
357
        ucl_decompress(bitmapdata[BMPIDX_INSTALLING], bitmapsize[BMPIDX_INSTALLING],
358
                       bmpbuffer, &dummy);
359
        renderbmp(lcdbuffer, bmpbuffer, 320);
360
        ucl_decompress(bitmapdata[BMPIDX_FORMATTING], bitmapsize[BMPIDX_FORMATTING],
361
                        bmpbuffer, &dummy);
362
        renderbmp(&lcdbuffer[320 * 36], bmpbuffer, 320);
363
        displaylcd(0, 319, 0, 239, lcdbuffer, 0);
364
        mkfat32(&progressbar);
365
    }
366
 
367
    ucl_decompress(bitmapdata[BMPIDX_COPYING], bitmapsize[BMPIDX_COPYING],
368
                   bmpbuffer, &dummy);
369
    renderbmp(&lcdbuffer[320 * 72], bmpbuffer, 320);
370
    displaylcd(0, 319, 0, 239, lcdbuffer, 0);
371
    int status;
372
    if (updating)
373
    {
374
        status = script[sp + 3];
375
        sp = script[sp + 1] >> 2;
376
    }
377
    else
378
    {
379
        status = script[sp + 2] + script[sp + 3];
380
        sp += 4;
381
    }
382
    progressbar_init(&progressbar, 5, 189, 101, 116, 0, 0xdefb, 0x1d, 0, status);
383
    status = 0;
384
    while (script[sp])
385
    {
386
        int fd;
387
        void* data;
388
        switch (script[sp])
389
        {
390
            case 1:
391
                mkdir(&scriptb[script[sp + 1]]);
392
                sp += 2;
393
                break;
394
            case 2:
395
                if (script[sp + 2] == 0xfffffffe && appleflash)
396
                {
397
                    data = oldnor;
398
                    script[sp + 3] = 0x100000;
399
                }
400
                else script[sp + 3] = 0;
401
                if (!script[sp + 3])
402
                {
403
                    sp += 4;
404
                    break;
405
                }
406
            case 3:
407
                fd = file_open(&scriptb[script[sp + 1]], O_RDONLY);
408
                if (fd >= 0)
409
                {
410
                    close(fd);
411
                    sp += 4;
412
                    break;
413
                }
414
            case 4:
415
                if (script[sp + 2] < 0xfffffffe) data = &scriptb[script[sp + 2]];
416
                fd = file_creat(&scriptb[script[sp + 1]]);
417
                if (fd >= 0)
418
                {
419
                    write(fd, data, script[sp + 3]);
420
                    close(fd);
421
                }
422
                sp += 4;
423
                break;
424
            default:
425
                panic(PANIC_KILLTHREAD, "Bad installation script!");
426
        }
427
        status += script[sp++];
428
        progressbar_setpos(&progressbar, status, false);
429
    }
430
 
431
    ucl_decompress(bitmapdata[BMPIDX_FLASHING], bitmapsize[BMPIDX_FLASHING], bmpbuffer, &dummy);
432
    renderbmp(&lcdbuffer[320 * 108], bmpbuffer, 320);
433
    displaylcd(0, 319, 0, 239, lcdbuffer, 0);
434
    progressbar_init(&progressbar, 5, 189, 162, 178, 0, 0xdefb, 0x1d, 0, 256);
435
    for (i = 0; i < 256; i++)
436
    {
437
        bootflash_writeraw(&norbuf[i << 12], i << 12, 1 << 12);
438
        progressbar_setpos(&progressbar, i, false);
439
    }
440
 
441
    shutdown(true);
442
    reset();
443
}