Subversion Repositories freemyipod

Rev

Rev 954 | Rev 956 | 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
        }
880 theseven 97
        else for (i = 0; i < 16; i++) SHA1DATAIN[i] = *databuf++;
955 theseven 98
        clean_dcache();  // Not sure why we need this, but apparently we do...
366 theseven 99
        SHA1CONFIG |= 2;
955 theseven 100
        invalidate_dcache();  // Not sure why we need this, but apparently we do...
366 theseven 101
        while (SHA1CONFIG & 1) sleep(0);
102
        SHA1CONFIG |= 8;
103
    }
880 theseven 104
    for (i = 0; i < 5; i++) *hashbuf++ = SHA1RESULT[i];
366 theseven 105
    clockgate_enable(0, false);
106
}
107
 
108
 
875 theseven 109
static void handler(void* user, enum button_event eventtype, int which, int value)
366 theseven 110
{
111
    if (eventtype == BUTTON_PRESS) button |= 1 << which;
630 theseven 112
    if (eventtype == BUTTON_RELEASE) button &= ~(1 << which);
530 theseven 113
    if (eventtype == WHEEL_MOVED_ACCEL)
114
        scrollpos = MAX(0, MIN(295, scrollpos + value / 8));
366 theseven 115
    wakeup_signal(&eventwakeup);
116
}
117
 
875 theseven 118
static void fat32_progressbar_init(void* user, int max)
366 theseven 119
{
660 theseven 120
    progressbar_init((struct progressbar_state*)user,
121
                     15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, max);
366 theseven 122
}
123
 
875 theseven 124
static void fat32_progressbar_update(void* user, int current)
660 theseven 125
{
126
    progressbar_setpos((struct progressbar_state*)user, current, false);
127
}
128
 
875 theseven 129
static void main(int argc, const char** argv)
366 theseven 130
{
131
    uint32_t i, j, k, rc;
132
    uint32_t dummy;
133
    struct progressbar_state progressbar;
660 theseven 134
    bool appleflash = false;
135
    bool oldflash;
366 theseven 136
    void* syscfgptr;
137
    uint8_t* norbuf;
138
#define norbufword ((uint32_t*)norbuf)
139
    uint8_t* oldnor;
140
#define oldnorword ((uint32_t*)oldnor)
141
 
530 theseven 142
    cputc(3, '.');
651 theseven 143
    struct emcorelib_header* libpng = get_library(LIBPNG_IDENTIFIER, LIBPNG_API_VERSION, LIBSOURCE_RAM_NEEDCOPY, f_png_emcorelib);
551 theseven 144
    if (!libpng) panicf(PANIC_KILLTHREAD, "Could not load PNG decoder library!");
530 theseven 145
    struct libpng_api* png = (struct libpng_api*)libpng->api;
146
    cputc(3, '.');
651 theseven 147
    struct emcorelib_header* libui = get_library(LIBUI_IDENTIFIER, LIBUI_API_VERSION, LIBSOURCE_RAM_NEEDCOPY, f_ui_emcorelib);
551 theseven 148
    if (!libui) panicf(PANIC_KILLTHREAD, "Could not load user interface library!");
530 theseven 149
    struct libui_api* ui = (struct libui_api*)libui->api;
150
    cputc(3, '.');
660 theseven 151
    struct emcorelib_header* libmkfat32 = get_library(LIBMKFAT32_IDENTIFIER, LIBMKFAT32_API_VERSION, LIBSOURCE_RAM_NEEDCOPY, f_mkfat32_emcorelib);
152
    if (!libmkfat32) panicf(PANIC_KILLTHREAD, "Could not load mkfat32 library!");
153
    struct libmkfat32_api* mf32 = (struct libmkfat32_api*)libmkfat32->api;
154
    cputc(3, '.');
366 theseven 155
 
530 theseven 156
    struct png_info* handle = png->png_open(background_png, background_png_size);
551 theseven 157
    if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse background image!");
530 theseven 158
    cputc(3, '.');
159
    struct png_rgb* bg = png->png_decode_rgb(handle);
551 theseven 160
    if (!bg) panicf(PANIC_KILLTHREAD, "Could not decode background image!");
530 theseven 161
    png->png_destroy(handle);
162
    cputc(3, '.');
163
    handle = png->png_open(actions_png, actions_png_size);
551 theseven 164
    if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse actions image!");
530 theseven 165
    cputc(3, '.');
166
    struct png_rgba* actions = png->png_decode_rgba(handle);
551 theseven 167
    if (!actions) panicf(PANIC_KILLTHREAD, "Could not decode actions image!");
530 theseven 168
    png->png_destroy(handle);
169
    cputc(3, '.');
170
    void* framebuf = malloc(290 * 165 * 3);
551 theseven 171
    if (!framebuf) panicf(PANIC_KILLTHREAD, "Could not allocate frame buffer!");
530 theseven 172
    cputc(3, '.');
366 theseven 173
 
530 theseven 174
    disk_unmount(0);
175
    bool updating = disk_mount(0);
176
    cputc(3, '.');
366 theseven 177
 
546 theseven 178
    norbuf = memalign(0x10, 0x100000);
179
    oldnor = memalign(0x10, 0x100000);
385 theseven 180
    memset(norbuf, 0xff, 0x100000);
530 theseven 181
    cputc(3, '.');
366 theseven 182
    bootflash_readraw(oldnor, 0, 0x100000);
530 theseven 183
    cputc(3, '.');
660 theseven 184
    if (oldnorword[0x400] == 0x53436667) oldflash = true;
366 theseven 185
    else
186
    {
660 theseven 187
        if (oldnorword[0] == 0x53436667) oldflash = false;
551 theseven 188
        else panic(PANIC_KILLTHREAD, "Boot flash contents are damaged! "
366 theseven 189
                                     "(No SYSCFG found)\n\nPlease ask for help.\n");
660 theseven 190
        if (oldnorword[0x400] == 0xffffffff && oldnorword[0x3ff80] == 0x666c7368)
191
        {
192
            appleflash = true;
193
            updating = false;
194
        }
366 theseven 195
    }
660 theseven 196
    memcpy(norbuf, &oldnor[oldflash ? 0x1000 : 0], 0x1000);
530 theseven 197
    cputc(3, '.');
198
 
199
    uint32_t* script = flashscript;
366 theseven 200
    uint32_t sp = 0;
201
    uint32_t beginptr = 0x2000;
202
    uint32_t endptr = 0x100000;
660 theseven 203
    uint32_t dirptr = 0x1000;
366 theseven 204
    while (script[sp])
205
    {
206
        uint32_t file = script[sp] & 0xff;
207
        uint32_t flags = (script[sp] >> 8) & 0xff;
208
        uint32_t align = (script[sp] >> 16) & 0xff;
209
        void* data;
210
        uint32_t size;
211
        sp++;
212
        switch (file)
213
        {
214
            default:
530 theseven 215
                data = (void*)(script[sp++]);
366 theseven 216
                size = script[sp++];
217
        }
218
        if (size)
219
        {
220
            if (align && !(flags & 1))
221
            {
222
                if ((align << 12) < beginptr)
551 theseven 223
                    panicf(PANIC_KILLTHREAD, "Error: Align failed! (%02X)", align);
366 theseven 224
                beginptr = align << 12;
225
            }
226
            if (endptr - beginptr < size)
551 theseven 227
                panicf(PANIC_KILLTHREAD, "Error: Flash is full!");
366 theseven 228
            uint32_t storesize = size;
229
            if (flags & 2) storesize |= 0x80000000;
230
            int offs = 0;
231
            if (flags & 8)
232
            {
233
                offs = 0x800;
954 theseven 234
                size = ((size + 0xf) & ~0xf);
366 theseven 235
            }
236
            if (flags & 1)
237
            {
954 theseven 238
                endptr -= ((offs + size + 0xfff) & ~0xfff);
366 theseven 239
                file = endptr;
240
            }
241
            else
242
            {
243
                file = beginptr;
954 theseven 244
                beginptr += ((offs + size + 0xfff) & ~0xfff);
366 theseven 245
            }
954 theseven 246
            memcpy(&norbuf[file + offs], data, size);
366 theseven 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
                memset(&norbuf[file], 0, 0x800);
260
                memcpy(&norbuf[file], "87021.0\x01", 8);
261
                *((uint32_t*)&norbuf[file + 0xc]) = size;
262
                sha1(&norbuf[file + 0x800], size, &norbuf[file + 0x10]);
263
                *((uint32_t*)&norbuf[file + 0x20]) = 0;
264
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x10], 0x10);
265
                sha1(&norbuf[file], 0x40, &norbuf[file + 0x40]);
266
                *((uint32_t*)&norbuf[file + 0x50]) = 0;
267
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x40], 0x10);
268
                hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[file + 0x800], size);
269
            }
270
        }
271
        else if (!(flags & 4)) sp += 2;
530 theseven 272
        cputc(3, '.');
366 theseven 273
    }
274
 
275
    if (!updating)
276
    {
530 theseven 277
        void* darkened = malloc(320 * 240 * 3);
551 theseven 278
        if (!darkened) panicf(PANIC_KILLTHREAD, "Could not allocate darkened image!");
530 theseven 279
        cputc(3, '.');
280
        handle = png->png_open(darkener_png, darkener_png_size);
551 theseven 281
        if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse darkener image!");
530 theseven 282
        cputc(3, '.');
283
        struct png_rgba* darkener = png->png_decode_rgba(handle);
551 theseven 284
        if (!darkener) panicf(PANIC_KILLTHREAD, "Could not decode darkener image!");
530 theseven 285
        png->png_destroy(handle);
286
        cputc(3, '.');
287
        ui->blenda(320, 240, 255, darkened, 0, 0, 320, bg, 0, 0, 320, darkener, 0, 0, 320);
288
        free(darkener);
289
        cputc(3, '.');
290
        handle = png->png_open(disclaimer_png, disclaimer_png_size);
551 theseven 291
        if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse disclaimer image!");
530 theseven 292
        cputc(3, '.');
293
        struct png_rgba* disclaimer = png->png_decode_rgba(handle);
551 theseven 294
        if (!disclaimer) panicf(PANIC_KILLTHREAD, "Could not decode disclaimer image!");
530 theseven 295
        png->png_destroy(handle);
296
        cputc(3, '.');
297
 
298
        button = 0;
299
        wakeup_init(&eventwakeup);
300
        struct button_hook_entry* hook = button_register_handler(handler, NULL);
551 theseven 301
        if (!hook) panicf(PANIC_KILLTHREAD, "Could not register button hook!");
530 theseven 302
 
303
        displaylcd(0, 0, 320, 240, darkened, 0, 0, 320);
304
        backlight_set_fade(32);
305
        backlight_set_brightness(177);
306
        backlight_on(true);
307
        scrollpos = 0;
308
 
366 theseven 309
        while (true)
310
        {
530 theseven 311
            ui->blenda(290, 165, 255, framebuf, 0, 0, 290,
312
                       darkened, 15, 50, 320, disclaimer, 0, scrollpos, 290);
313
            displaylcd(15, 50, 290, 165, framebuf, 0, 0, 290);
314
 
366 theseven 315
            wakeup_wait(&eventwakeup, TIMEOUT_BLOCK);
530 theseven 316
            if (button == 0x18) break;
366 theseven 317
            else if (button == 4)
318
            {
385 theseven 319
                shutdown(false);
366 theseven 320
                reset();
321
            }
322
        }
530 theseven 323
 
324
        button_unregister_handler(hook);
325
        free(darkened);
326
        free(disclaimer);
327
 
328
        ui->blenda(165, 36, 255, framebuf, 0, 0, 165, bg, 77, 100, 320, actions, 0, 0, 165);
329
        displaylcd(0, 0, 320, 240, bg, 0, 0, 320);
330
        displaylcd(77, 100, 165, 36, framebuf, 0, 0, 165);
331
 
660 theseven 332
        struct storage_info storageinfo;
333
        storage_get_info(0, &storageinfo);
334
        int rc = mf32->mkfat32(0, 0, storageinfo.num_sectors, 4096, 1, "iPodClassic", &progressbar,
335
                              fat32_progressbar_init, fat32_progressbar_update);
336
        if (rc < 0) panicf(PANIC_KILLTHREAD, "Error formatting hard drive: %08X", rc);
366 theseven 337
    }
338
 
530 theseven 339
    ui->blenda(165, 36, 255, framebuf, 0, 0, 165, bg, 77, 100, 320, actions, 0, 36, 165);
340
    displaylcd(0, 0, 320, 240, bg, 0, 0, 320);
341
    displaylcd(77, 100, 165, 36, framebuf, 0, 0, 165);
342
    backlight_set_fade(32);
343
    backlight_set_brightness(177);
344
    backlight_on(true);
551 theseven 345
 
858 farthen 346
    remove("/.boot/init.emcoreapp");
530 theseven 347
    int cost;
366 theseven 348
    if (updating)
349
    {
530 theseven 350
        cost = commoncost;
351
        script = commonscript;
366 theseven 352
    }
353
    else
354
    {
530 theseven 355
        cost = firstinstcost + commoncost;
356
        script = firstinstscript;
366 theseven 357
    }
547 theseven 358
    progressbar_init(&progressbar, 15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, cost);
530 theseven 359
    sp = 0;
360
    cost = 0;
366 theseven 361
    while (script[sp])
362
    {
363
        int fd;
364
        void* data;
365
        switch (script[sp])
366
        {
367
            case 1:
530 theseven 368
                mkdir((char*)(script[sp + 1]));
366 theseven 369
                sp += 2;
370
                break;
371
            case 2:
372
                if (script[sp + 2] == 0xfffffffe && appleflash)
373
                {
374
                    data = oldnor;
375
                    script[sp + 3] = 0x100000;
376
                }
385 theseven 377
                else if (script[sp + 2] == 0xfffffffe) script[sp + 3] = 0;
366 theseven 378
                if (!script[sp + 3])
379
                {
380
                    sp += 4;
381
                    break;
382
                }
383
            case 3:
530 theseven 384
                fd = file_open((char*)(script[sp + 1]), O_RDONLY);
366 theseven 385
                if (fd >= 0)
386
                {
387
                    close(fd);
388
                    sp += 4;
389
                    break;
390
                }
391
            case 4:
530 theseven 392
                if (script[sp + 2] < 0xfffffffe) data = (void*)(script[sp + 2]);
393
                fd = file_creat((char*)(script[sp + 1]));
366 theseven 394
                if (fd >= 0)
395
                {
396
                    write(fd, data, script[sp + 3]);
397
                    close(fd);
398
                }
399
                sp += 4;
400
                break;
401
            default:
551 theseven 402
                panic(PANIC_KILLTHREAD, "Bad installation script!");
366 theseven 403
        }
530 theseven 404
        cost += script[sp++];
405
        progressbar_setpos(&progressbar, cost, false);
366 theseven 406
    }
546 theseven 407
 
408
    if (oldnor) free(oldnor);
409
 
530 theseven 410
    ui->blenda(165, 36, 255, framebuf, 0, 0, 165, bg, 77, 100, 320, actions, 0, 72, 165);
411
    displaylcd(77, 100, 165, 36, framebuf, 0, 0, 165);
412
    progressbar_init(&progressbar, 15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, 256);
366 theseven 413
    for (i = 0; i < 256; i++)
414
    {
415
        bootflash_writeraw(&norbuf[i << 12], i << 12, 1 << 12);
416
        progressbar_setpos(&progressbar, i, false);
417
    }
418
 
546 theseven 419
    free(norbuf);
420
    free(framebuf);
421
    free(actions);
422
    free(bg);
423
 
660 theseven 424
    release_library(libmkfat32);
546 theseven 425
    release_library(libui);
426
    release_library(libpng);
660 theseven 427
    library_unload(libmkfat32);
546 theseven 428
    library_unload(libui);
429
    library_unload(libpng);
430
 
385 theseven 431
    shutdown(false);
366 theseven 432
    reset();
433
}