Subversion Repositories freemyipod

Rev

Rev 858 | Rev 880 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
366 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
530 theseven 6
//    This file is part of emCORE.
366 theseven 7
//
530 theseven 8
//    emCORE is free software: you can redistribute it and/or
366 theseven 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
//
530 theseven 13
//    emCORE is distributed in the hope that it will be useful,
366 theseven 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
530 theseven 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
366 theseven 20
//
21
//
22
 
23
 
530 theseven 24
#include "emcoreapp.h"
25
#include "libpng.h"
26
#include "libui.h"
660 theseven 27
#include "libmkfat32.h"
366 theseven 28
 
29
 
875 theseven 30
static void main(int argc, const char** argv);
530 theseven 31
EMCORE_APP_HEADER("emCORE installer", main, 127)
366 theseven 32
 
33
 
530 theseven 34
extern char background_png[];
35
extern uint32_t background_png_size;
36
extern char darkener_png[];
37
extern uint32_t darkener_png_size;
38
extern char disclaimer_png[];
39
extern uint32_t disclaimer_png_size;
40
extern char actions_png[];
41
extern uint32_t actions_png_size;
42
extern char f_png_emcorelib[];
43
extern char f_ui_emcorelib[];
660 theseven 44
extern char f_mkfat32_emcorelib[];
530 theseven 45
extern uint32_t flashscript[];
46
extern uint32_t firstinstcost;
47
extern uint32_t firstinstscript[];
48
extern uint32_t commoncost;
49
extern uint32_t commonscript[];
366 theseven 50
 
530 theseven 51
 
875 theseven 52
static struct wakeup eventwakeup;
53
static volatile int button;
54
static volatile int scrollpos;
366 theseven 55
 
56
 
57
#define SHA1CONFIG    (*((volatile uint32_t*)(0x38000000)))
58
#define SHA1RESET     (*((volatile uint32_t*)(0x38000004)))
59
#define SHA1RESULT      ((volatile uint32_t*)(0x38000020))
60
#define SHA1DATAIN      ((volatile uint32_t*)(0x38000040))
61
 
875 theseven 62
static void sha1(void* data, uint32_t size, void* hash)
366 theseven 63
{
64
    int i, space;
65
    bool done = false;
66
    uint32_t tmp32[16];
67
    uint8_t* tmp8 = (uint8_t*)tmp32;
68
    uint32_t* databuf = (uint32_t*)data;
69
    uint32_t* hashbuf = (uint32_t*)hash;
70
    clockgate_enable(0, true);
71
    SHA1RESET = 1;
72
    while (SHA1CONFIG & 1) sleep(0);
73
    SHA1RESET = 0;
74
    SHA1CONFIG = 0;
75
    while (!done)
76
    {
77
        space = ((uint32_t)databuf) - ((uint32_t)data) - size + 64;
78
        if (space > 0)
79
        {
80
            for (i = 0; i < 16; i++) tmp32[i] = 0;
81
            if (space <= 64)
82
            {
83
                for (i = 0; i < 64 - space; i++) tmp8[i] = ((uint8_t*)databuf)[i];
84
                tmp8[64 - space] = 0x80;
85
            }
86
            if (space >= 8)
87
            {
88
                tmp8[0x3b] = (size >> 29) & 0xff;
89
                tmp8[0x3c] = (size >> 21) & 0xff;
90
                tmp8[0x3d] = (size >> 13) & 0xff;
91
                tmp8[0x3e] = (size >> 5) & 0xff;
92
                tmp8[0x3f] = (size << 3) & 0xff;
93
                done = true;
94
            }
95
            for (i = 0; i < 16; i++) SHA1DATAIN[i] = tmp32[i];
96
        }
97
        else for (i = 0; i < 16; i++) SHA1DATAIN[i] = databuf[i];
98
        databuf += 16;
99
        SHA1CONFIG |= 2;
100
        while (SHA1CONFIG & 1) sleep(0);
101
        SHA1CONFIG |= 8;
102
    }
103
    for (i = 0; i < 5; i++) hashbuf[i] = SHA1RESULT[i];
104
    clockgate_enable(0, false);
105
}
106
 
107
 
875 theseven 108
static void handler(void* user, enum button_event eventtype, int which, int value)
366 theseven 109
{
110
    if (eventtype == BUTTON_PRESS) button |= 1 << which;
630 theseven 111
    if (eventtype == BUTTON_RELEASE) button &= ~(1 << which);
530 theseven 112
    if (eventtype == WHEEL_MOVED_ACCEL)
113
        scrollpos = MAX(0, MIN(295, scrollpos + value / 8));
366 theseven 114
    wakeup_signal(&eventwakeup);
115
}
116
 
875 theseven 117
static void fat32_progressbar_init(void* user, int max)
366 theseven 118
{
660 theseven 119
    progressbar_init((struct progressbar_state*)user,
120
                     15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, max);
366 theseven 121
}
122
 
875 theseven 123
static void fat32_progressbar_update(void* user, int current)
660 theseven 124
{
125
    progressbar_setpos((struct progressbar_state*)user, current, false);
126
}
127
 
875 theseven 128
static void main(int argc, const char** argv)
366 theseven 129
{
130
    uint32_t i, j, k, rc;
131
    uint32_t dummy;
132
    struct progressbar_state progressbar;
660 theseven 133
    bool appleflash = false;
134
    bool oldflash;
366 theseven 135
    void* syscfgptr;
136
    uint8_t* norbuf;
137
#define norbufword ((uint32_t*)norbuf)
138
    uint8_t* oldnor;
139
#define oldnorword ((uint32_t*)oldnor)
140
 
530 theseven 141
    cputc(3, '.');
651 theseven 142
    struct emcorelib_header* libpng = get_library(LIBPNG_IDENTIFIER, LIBPNG_API_VERSION, LIBSOURCE_RAM_NEEDCOPY, f_png_emcorelib);
551 theseven 143
    if (!libpng) panicf(PANIC_KILLTHREAD, "Could not load PNG decoder library!");
530 theseven 144
    struct libpng_api* png = (struct libpng_api*)libpng->api;
145
    cputc(3, '.');
651 theseven 146
    struct emcorelib_header* libui = get_library(LIBUI_IDENTIFIER, LIBUI_API_VERSION, LIBSOURCE_RAM_NEEDCOPY, f_ui_emcorelib);
551 theseven 147
    if (!libui) panicf(PANIC_KILLTHREAD, "Could not load user interface library!");
530 theseven 148
    struct libui_api* ui = (struct libui_api*)libui->api;
149
    cputc(3, '.');
660 theseven 150
    struct emcorelib_header* libmkfat32 = get_library(LIBMKFAT32_IDENTIFIER, LIBMKFAT32_API_VERSION, LIBSOURCE_RAM_NEEDCOPY, f_mkfat32_emcorelib);
151
    if (!libmkfat32) panicf(PANIC_KILLTHREAD, "Could not load mkfat32 library!");
152
    struct libmkfat32_api* mf32 = (struct libmkfat32_api*)libmkfat32->api;
153
    cputc(3, '.');
366 theseven 154
 
530 theseven 155
    struct png_info* handle = png->png_open(background_png, background_png_size);
551 theseven 156
    if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse background image!");
530 theseven 157
    cputc(3, '.');
158
    struct png_rgb* bg = png->png_decode_rgb(handle);
551 theseven 159
    if (!bg) panicf(PANIC_KILLTHREAD, "Could not decode background image!");
530 theseven 160
    png->png_destroy(handle);
161
    cputc(3, '.');
162
    handle = png->png_open(actions_png, actions_png_size);
551 theseven 163
    if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse actions image!");
530 theseven 164
    cputc(3, '.');
165
    struct png_rgba* actions = png->png_decode_rgba(handle);
551 theseven 166
    if (!actions) panicf(PANIC_KILLTHREAD, "Could not decode actions image!");
530 theseven 167
    png->png_destroy(handle);
168
    cputc(3, '.');
169
    void* framebuf = malloc(290 * 165 * 3);
551 theseven 170
    if (!framebuf) panicf(PANIC_KILLTHREAD, "Could not allocate frame buffer!");
530 theseven 171
    cputc(3, '.');
366 theseven 172
 
530 theseven 173
    disk_unmount(0);
174
    bool updating = disk_mount(0);
175
    cputc(3, '.');
366 theseven 176
 
546 theseven 177
    norbuf = memalign(0x10, 0x100000);
178
    oldnor = memalign(0x10, 0x100000);
385 theseven 179
    memset(norbuf, 0xff, 0x100000);
530 theseven 180
    cputc(3, '.');
366 theseven 181
    bootflash_readraw(oldnor, 0, 0x100000);
530 theseven 182
    cputc(3, '.');
660 theseven 183
    if (oldnorword[0x400] == 0x53436667) oldflash = true;
366 theseven 184
    else
185
    {
660 theseven 186
        if (oldnorword[0] == 0x53436667) oldflash = false;
551 theseven 187
        else panic(PANIC_KILLTHREAD, "Boot flash contents are damaged! "
366 theseven 188
                                     "(No SYSCFG found)\n\nPlease ask for help.\n");
660 theseven 189
        if (oldnorword[0x400] == 0xffffffff && oldnorword[0x3ff80] == 0x666c7368)
190
        {
191
            appleflash = true;
192
            updating = false;
193
        }
366 theseven 194
    }
660 theseven 195
    memcpy(norbuf, &oldnor[oldflash ? 0x1000 : 0], 0x1000);
530 theseven 196
    cputc(3, '.');
197
 
198
    uint32_t* script = flashscript;
366 theseven 199
    uint32_t sp = 0;
200
    uint32_t beginptr = 0x2000;
201
    uint32_t endptr = 0x100000;
660 theseven 202
    uint32_t dirptr = 0x1000;
366 theseven 203
    while (script[sp])
204
    {
205
        uint32_t file = script[sp] & 0xff;
206
        uint32_t flags = (script[sp] >> 8) & 0xff;
207
        uint32_t align = (script[sp] >> 16) & 0xff;
208
        void* data;
209
        uint32_t size;
210
        sp++;
211
        switch (file)
212
        {
213
            default:
530 theseven 214
                data = (void*)(script[sp++]);
366 theseven 215
                size = script[sp++];
216
        }
217
        if (size)
218
        {
219
            if (align && !(flags & 1))
220
            {
221
                if ((align << 12) < beginptr)
551 theseven 222
                    panicf(PANIC_KILLTHREAD, "Error: Align failed! (%02X)", align);
366 theseven 223
                beginptr = align << 12;
224
            }
225
            if (endptr - beginptr < size)
551 theseven 226
                panicf(PANIC_KILLTHREAD, "Error: Flash is full!");
366 theseven 227
            uint32_t storesize = size;
228
            if (flags & 2) storesize |= 0x80000000;
229
            int offs = 0;
230
            if (flags & 8)
231
            {
232
                offs = 0x800;
233
                size = ((size + 0xf) & ~0xf) + offs;
234
            }
235
            if (flags & 1)
236
            {
237
                endptr -= ((size + 0xfff) & ~0xfff);
238
                memcpy(&norbuf[endptr + offs], data, size);
239
                file = endptr;
240
            }
241
            else
242
            {
243
                memcpy(&norbuf[beginptr + offs], data, size);
244
                file = beginptr;
245
                beginptr += ((size + 0xfff) & ~0xfff);
246
            }
247
            if (!(flags & 4))
248
            {
660 theseven 249
                if (dirptr >= 0x2000)
551 theseven 250
                    panicf(PANIC_KILLTHREAD, "Error: Directory is full!");
366 theseven 251
                memcpy(&norbuf[dirptr], &script[sp], 8);
252
                norbufword[(dirptr >> 2) + 2] = file;
253
                norbufword[(dirptr >> 2) + 3] = storesize;
254
                dirptr += 0x10;
255
                sp += 2;
256
            }
257
            if (flags & 8)
258
            {
259
                size -= offs;
260
                memset(&norbuf[file], 0, 0x800);
261
                memcpy(&norbuf[file], "87021.0\x01", 8);
262
                *((uint32_t*)&norbuf[file + 0xc]) = size;
263
                sha1(&norbuf[file + 0x800], size, &norbuf[file + 0x10]);
264
                *((uint32_t*)&norbuf[file + 0x20]) = 0;
265
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x10], 0x10);
266
                sha1(&norbuf[file], 0x40, &norbuf[file + 0x40]);
267
                *((uint32_t*)&norbuf[file + 0x50]) = 0;
268
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x40], 0x10);
269
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x800], size);
270
            }
271
        }
272
        else if (!(flags & 4)) sp += 2;
530 theseven 273
        cputc(3, '.');
366 theseven 274
    }
275
 
276
    if (!updating)
277
    {
530 theseven 278
        void* darkened = malloc(320 * 240 * 3);
551 theseven 279
        if (!darkened) panicf(PANIC_KILLTHREAD, "Could not allocate darkened image!");
530 theseven 280
        cputc(3, '.');
281
        handle = png->png_open(darkener_png, darkener_png_size);
551 theseven 282
        if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse darkener image!");
530 theseven 283
        cputc(3, '.');
284
        struct png_rgba* darkener = png->png_decode_rgba(handle);
551 theseven 285
        if (!darkener) panicf(PANIC_KILLTHREAD, "Could not decode darkener image!");
530 theseven 286
        png->png_destroy(handle);
287
        cputc(3, '.');
288
        ui->blenda(320, 240, 255, darkened, 0, 0, 320, bg, 0, 0, 320, darkener, 0, 0, 320);
289
        free(darkener);
290
        cputc(3, '.');
291
        handle = png->png_open(disclaimer_png, disclaimer_png_size);
551 theseven 292
        if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse disclaimer image!");
530 theseven 293
        cputc(3, '.');
294
        struct png_rgba* disclaimer = png->png_decode_rgba(handle);
551 theseven 295
        if (!disclaimer) panicf(PANIC_KILLTHREAD, "Could not decode disclaimer image!");
530 theseven 296
        png->png_destroy(handle);
297
        cputc(3, '.');
298
 
299
        button = 0;
300
        wakeup_init(&eventwakeup);
301
        struct button_hook_entry* hook = button_register_handler(handler, NULL);
551 theseven 302
        if (!hook) panicf(PANIC_KILLTHREAD, "Could not register button hook!");
530 theseven 303
 
304
        displaylcd(0, 0, 320, 240, darkened, 0, 0, 320);
305
        backlight_set_fade(32);
306
        backlight_set_brightness(177);
307
        backlight_on(true);
308
        scrollpos = 0;
309
 
366 theseven 310
        while (true)
311
        {
530 theseven 312
            ui->blenda(290, 165, 255, framebuf, 0, 0, 290,
313
                       darkened, 15, 50, 320, disclaimer, 0, scrollpos, 290);
314
            displaylcd(15, 50, 290, 165, framebuf, 0, 0, 290);
315
 
366 theseven 316
            wakeup_wait(&eventwakeup, TIMEOUT_BLOCK);
530 theseven 317
            if (button == 0x18) break;
366 theseven 318
            else if (button == 4)
319
            {
385 theseven 320
                shutdown(false);
366 theseven 321
                reset();
322
            }
323
        }
530 theseven 324
 
325
        button_unregister_handler(hook);
326
        free(darkened);
327
        free(disclaimer);
328
 
329
        ui->blenda(165, 36, 255, framebuf, 0, 0, 165, bg, 77, 100, 320, actions, 0, 0, 165);
330
        displaylcd(0, 0, 320, 240, bg, 0, 0, 320);
331
        displaylcd(77, 100, 165, 36, framebuf, 0, 0, 165);
332
 
660 theseven 333
        struct storage_info storageinfo;
334
        storage_get_info(0, &storageinfo);
335
        int rc = mf32->mkfat32(0, 0, storageinfo.num_sectors, 4096, 1, "iPodClassic", &progressbar,
336
                              fat32_progressbar_init, fat32_progressbar_update);
337
        if (rc < 0) panicf(PANIC_KILLTHREAD, "Error formatting hard drive: %08X", rc);
366 theseven 338
    }
339
 
530 theseven 340
    ui->blenda(165, 36, 255, framebuf, 0, 0, 165, bg, 77, 100, 320, actions, 0, 36, 165);
341
    displaylcd(0, 0, 320, 240, bg, 0, 0, 320);
342
    displaylcd(77, 100, 165, 36, framebuf, 0, 0, 165);
343
    backlight_set_fade(32);
344
    backlight_set_brightness(177);
345
    backlight_on(true);
551 theseven 346
 
858 farthen 347
    remove("/.boot/init.emcoreapp");
530 theseven 348
    int cost;
366 theseven 349
    if (updating)
350
    {
530 theseven 351
        cost = commoncost;
352
        script = commonscript;
366 theseven 353
    }
354
    else
355
    {
530 theseven 356
        cost = firstinstcost + commoncost;
357
        script = firstinstscript;
366 theseven 358
    }
547 theseven 359
    progressbar_init(&progressbar, 15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, cost);
530 theseven 360
    sp = 0;
361
    cost = 0;
366 theseven 362
    while (script[sp])
363
    {
364
        int fd;
365
        void* data;
366
        switch (script[sp])
367
        {
368
            case 1:
530 theseven 369
                mkdir((char*)(script[sp + 1]));
366 theseven 370
                sp += 2;
371
                break;
372
            case 2:
373
                if (script[sp + 2] == 0xfffffffe && appleflash)
374
                {
375
                    data = oldnor;
376
                    script[sp + 3] = 0x100000;
377
                }
385 theseven 378
                else if (script[sp + 2] == 0xfffffffe) script[sp + 3] = 0;
366 theseven 379
                if (!script[sp + 3])
380
                {
381
                    sp += 4;
382
                    break;
383
                }
384
            case 3:
530 theseven 385
                fd = file_open((char*)(script[sp + 1]), O_RDONLY);
366 theseven 386
                if (fd >= 0)
387
                {
388
                    close(fd);
389
                    sp += 4;
390
                    break;
391
                }
392
            case 4:
530 theseven 393
                if (script[sp + 2] < 0xfffffffe) data = (void*)(script[sp + 2]);
394
                fd = file_creat((char*)(script[sp + 1]));
366 theseven 395
                if (fd >= 0)
396
                {
397
                    write(fd, data, script[sp + 3]);
398
                    close(fd);
399
                }
400
                sp += 4;
401
                break;
402
            default:
551 theseven 403
                panic(PANIC_KILLTHREAD, "Bad installation script!");
366 theseven 404
        }
530 theseven 405
        cost += script[sp++];
406
        progressbar_setpos(&progressbar, cost, false);
366 theseven 407
    }
546 theseven 408
 
409
    if (oldnor) free(oldnor);
410
 
530 theseven 411
    ui->blenda(165, 36, 255, framebuf, 0, 0, 165, bg, 77, 100, 320, actions, 0, 72, 165);
412
    displaylcd(77, 100, 165, 36, framebuf, 0, 0, 165);
413
    progressbar_init(&progressbar, 15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, 256);
366 theseven 414
    for (i = 0; i < 256; i++)
415
    {
416
        bootflash_writeraw(&norbuf[i << 12], i << 12, 1 << 12);
417
        progressbar_setpos(&progressbar, i, false);
418
    }
419
 
546 theseven 420
    free(norbuf);
421
    free(framebuf);
422
    free(actions);
423
    free(bg);
424
 
660 theseven 425
    release_library(libmkfat32);
546 theseven 426
    release_library(libui);
427
    release_library(libpng);
660 theseven 428
    library_unload(libmkfat32);
546 theseven 429
    library_unload(libui);
430
    library_unload(libpng);
431
 
385 theseven 432
    shutdown(false);
366 theseven 433
    reset();
434
}