Subversion Repositories freemyipod

Rev

Rev 670 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
150 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
652 theseven 6
//    This file is part of emCORE.
150 theseven 7
//
652 theseven 8
//    emCORE is free software: you can redistribute it and/or
150 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
//
652 theseven 13
//    emCORE is distributed in the hope that it will be useful,
150 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
652 theseven 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
150 theseven 20
//
21
//
22
 
23
 
670 theseven 24
#include "emcoreapp.h"
25
#include "libboot.h"
145 theseven 26
 
27
 
835 theseven 28
void main(int argc, const char** argv);
670 theseven 29
EMCORE_APP_HEADER("emCORE uninstaller", main, 127)
145 theseven 30
 
31
 
32
struct wakeup eventwakeup;
33
volatile int button;
34
 
35
#define nor ((uint8_t*)0x24000000)
36
#define norword ((uint32_t*)0x24000000)
37
 
38
 
670 theseven 39
void handler(void* user, enum button_event eventtype, int which, int value)
145 theseven 40
{
41
    if (eventtype == BUTTON_PRESS) button |= 1 << which;
42
    wakeup_signal(&eventwakeup);
43
}
44
 
670 theseven 45
void* safe_memalign(size_t align, size_t size)
46
{
47
    void* addr = memalign(align, size);
48
    if (!addr) panicf(PANIC_KILLTHREAD, "Out of memory!");
49
    return addr;
50
}
51
 
145 theseven 52
uint32_t freeret(uint32_t rc, void* ptr)
53
{
670 theseven 54
    free(ptr);
145 theseven 55
    return rc;
56
}
57
 
58
uint32_t decryptfw(void* image, uint32_t offset)
59
{
60
    uint32_t size = ((uint32_t*)image)[5];
61
    if (size > 0x800000) return 0;
62
    hwkeyaes(HWKEYAES_DECRYPT, ((uint32_t*)image)[2], &((uint8_t*)image)[offset], size);
63
    memcpy(image, &((uint8_t*)image)[offset], size);
64
    return size;
65
}
66
 
67
uint32_t getfw(const char* filename, uint32_t* sector, uint32_t* size)
68
{
69
    uint32_t i;
670 theseven 70
    uint32_t* buffer = safe_memalign(0x10, 0x800);
145 theseven 71
    if (storage_read_sectors_md(0, 0, 1, buffer) != 0) return freeret(1, buffer);
72
    if (*((uint16_t*)((uint32_t)buffer + 0x1FE)) != 0xAA55) return freeret(1, buffer);
73
    uint32_t startsector = 0;
74
    for (i = 0x1C2; i < 0x200; i += 0x10)
75
        if (((uint8_t*)buffer)[i] == 0)
76
        {
77
            startsector = *((uint16_t*)((uint32_t)buffer + i + 4))
78
                        | (*((uint16_t*)((uint32_t)buffer + i + 6)) << 16);
79
            break;
80
        }
81
    if (startsector == 0) return freeret(1, buffer);
82
    if (storage_read_sectors_md(0, startsector, 1, buffer) != 0) return freeret(1, buffer);
83
    if (buffer[0x40] != 0x5B68695D) return freeret(1, buffer);
84
    if (storage_read_sectors_md(0, startsector + 1 + (buffer[0x41] >> 11), 1, buffer) != 0)
85
        return freeret(1, buffer);
86
    for (i = 0; i < 0x1FE; i += 10)
87
        if (memcmp(&buffer[i], filename, 8) == 0)
88
        {
89
            *sector = startsector + (buffer[i + 3] >> 11);
90
            *size = buffer[i + 4] + 0x800;
670 theseven 91
            free(buffer);
145 theseven 92
            return 0;
93
        }
94
    return freeret(2, buffer);
95
}
96
 
97
uint32_t readfw(const char* filename, void** address, uint32_t* size)
98
{
99
    uint32_t sector;
100
    uint32_t rc = getfw(filename, &sector, size);
101
    if (rc) return rc;
670 theseven 102
    *address = safe_memalign(0x10, *size);
145 theseven 103
    if (storage_read_sectors_md(0, sector, ((*size + 0x7FF) >> 11), *address) != 0)
104
        return freeret(1, *address);
105
    *size = decryptfw(*address, 0x800);
670 theseven 106
    *address = realloc(*address, *size);
145 theseven 107
    return 0;
108
}
109
 
835 theseven 110
void main(int argc, const char** argv)
145 theseven 111
{
112
    uint32_t i, j, k;
113
    uint8_t* aupd;
114
    uint32_t aupdsize;
115
	uint32_t payloadstart = 0;
116
    struct progressbar_state progressbar;
117
 
670 theseven 118
    cputc(1, '.');
145 theseven 119
 
120
    if (norword[0x400] != 0x53436667)
670 theseven 121
        panicf(PANIC_KILLTHREAD, "Boot flash contents are damaged! (No SYSCFG found)\n\n"
122
                                 "Please ask for help.");
145 theseven 123
 
124
    aupdsize = 0;
125
    if (readfw("DNANdpua", (void**)&aupd, &aupdsize)) aupdsize = 0;
670 theseven 126
    cputc(1, '.');
145 theseven 127
    if (!aupdsize)
128
    {
670 theseven 129
        cputs(3, "\n\nPlease press any key to\nenter disk mode and\nrestore your iPod using\n"
130
                 "iTunes. After your iPod\nreboots, run the\nuninstaller again.\n"
131
                 "If this message is still\nshown after restoring,\nplease ask for help.");
132
        wakeup_init(&eventwakeup);
133
        struct button_hook_entry* hook = button_register_handler(handler, NULL);
134
        if (!hook) panicf(PANIC_KILLTHREAD, "Could not register button hook!");
145 theseven 135
        button = 0;
136
        while (true)
137
        {
138
            wakeup_wait(&eventwakeup, TIMEOUT_BLOCK);
139
            if (button)
140
            {
670 theseven 141
                void* firmware = NULL;
142
                int size;
143
                struct emcorelib_header* lib = get_library(LIBBOOT_IDENTIFIER, LIBBOOT_API_VERSION,
144
                                                           LIBSOURCE_BOOTFLASH, "libboot ");
145
                if (!lib) panicf(PANIC_KILLTHREAD, "Could not load libboot!");
146
                struct libboot_api* boot = (struct libboot_api*)lib->api;
147
                boot->load_from_flash(&firmware, &size, false, "diskmode", 0x100000);
148
                release_library(lib);
149
                library_unload(lib);
150
                if (!firmware)
151
                    panicf(PANIC_KILLTHREAD, "Could not boot disk mode.\nPlease ask for help.");
152
                shutdown(false);
153
                execfirmware((void*)0x08000000, firmware, size);
145 theseven 154
            }
155
        }
156
    }
670 theseven 157
 
158
    cputc(1, '.');
159
    uint8_t* norbuf = (uint8_t*)safe_memalign(0x10, 0x100000);
160
    #define norbufword ((uint32_t*)norbuf)
161
    cputc(1, '.');
162
    memset(norbuf, 0xff, 0x100000);
163
    cputc(1, '.');
164
    memcpy(&norbuf[0x4000], &nor[0x1000], 0x1000);
165
    cputc(1, '.');
166
 
167
    for (i = 0; i < (aupdsize >> 2); i++)
145 theseven 168
		if (((uint32_t*)aupd)[i] == 0x50796c64 && ((uint32_t*)aupd)[i + 4] == 0x46775570)
169
		    payloadstart = i << 2;
170
	if (!payloadstart)
670 theseven 171
        panicf(PANIC_KILLTHREAD, "Restore image is weird:\nNo payload start found.\n"
172
                                 "Please ask for help.");
173
    cputc(1, '.');
145 theseven 174
	memcpy(norbuf, &aupd[payloadstart + 0x2c], 0x2000);
670 theseven 175
    cputc(1, '.');
145 theseven 176
	memcpy(&norbuf[0x8800], &aupd[payloadstart + 0x2048], 0x1f800);
670 theseven 177
    cputc(1, '.');
145 theseven 178
	memcpy(&norbuf[0x28000], &aupd[payloadstart + 0x22048], 0xd8000);
670 theseven 179
    cputc(1, '.');
180
	free(aupd);
145 theseven 181
 
182
    memset(&norbuf[0x8000], 0, 0x800);
670 theseven 183
    cputc(1, '.');
145 theseven 184
    norbufword[0x2000] = 0x31303738;
185
    norbufword[0x2001] = 0x00302e31;
186
    norbufword[0x2002] = 0x800;
187
    norbufword[0x2003] = 0x1f800;
670 theseven 188
    cputc(1, '.');
145 theseven 189
    hmacsha1(&norbuf[0x8800], 0x1f800, &norbuf[0x8010]);
670 theseven 190
    cputc(1, '.');
145 theseven 191
    hmacsha1(&norbuf[0x8000], 0x40, &norbuf[0x8040]);
670 theseven 192
    cputc(1, '.');
145 theseven 193
    hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbuf[0x8000], 0x20000);
670 theseven 194
    cputc(1, '.');
145 theseven 195
    for (i = 0xffe00; i < 0xffec8; i += 0x28)
196
        if (norbufword[i >> 2])
197
        {
198
            uint32_t offs = norbufword[(i >> 2) + 3] >> 2;
199
            norbufword[offs] = 0;
200
            norbufword[offs + 1] = 2;
201
            norbufword[offs + 2] = 2;
202
            norbufword[offs + 3] = 0x40;
203
            norbufword[offs + 4] = 0;
204
            norbufword[offs + 5] = norbufword[(i >> 2) + 4];
670 theseven 205
            cputc(1, '.');
145 theseven 206
            hmacsha1(&norbufword[offs + 0x80], norbufword[(i >> 2) + 4], &norbufword[offs + 7]);
670 theseven 207
            cputc(1, '.');
145 theseven 208
            memset(&norbufword[offs + 0x75], 0, 0x14);
670 theseven 209
            cputc(1, '.');
145 theseven 210
            hmacsha1(&norbufword[offs], 0x200, &norbufword[offs + 0x75]);
670 theseven 211
            cputc(1, '.');
145 theseven 212
            hwkeyaes(HWKEYAES_ENCRYPT, 2, &norbufword[offs + 0x80], norbufword[(i >> 2) + 4]);
670 theseven 213
            cputc(1, '.');
145 theseven 214
        }
215
 
670 theseven 216
    for (i = 0; i < 16; i++)
145 theseven 217
    {
670 theseven 218
        bootflash_writeraw(&norbuf[i * 0x10000], i * 0x10000, 0x10000);
219
        cputc(1, '.');
145 theseven 220
    }
670 theseven 221
    free(norbuf);
422 theseven 222
    shutdown(false);
145 theseven 223
    reset();
224
}