Subversion Repositories freemyipod

Rev

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