Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
243 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
677 theseven 6
//    This file is part of emCORE.
243 theseven 7
//
677 theseven 8
//    emCORE is free software: you can redistribute it and/or
243 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
//
677 theseven 13
//    emCORE is distributed in the hope that it will be useful,
243 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
677 theseven 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
243 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "power.h"
26
#include "interrupt.h"
27
#include "util.h"
28
#include "targetinit.h"
29
#ifdef HAVE_LCD
30
#include "lcd.h"
31
#include "lcdconsole.h"
32
#endif
33
#ifdef HAVE_I2C
34
#include "i2c.h"
35
#endif
36
#include "usb/usb.h"
37
#ifdef HAVE_BACKLIGHT
38
#include "backlight.h"
39
#endif
40
#include "ramdisk.h"
41
#include "timer.h"
42
 
43
 
44
static const char welcomestring[] INITCONST_ATTR = "UMSboot v" VERSION " r" VERSION_SVN "\n\n"
45
                                                   "Please copy a UBI file to\n"
46
                                                   "the mass storage device and\n"
47
                                                   "safely eject and unplug it\n"
48
                                                   "when you're done.\n\n"
49
                                                   "If you booted this\n"
50
                                                   "accidentally, just press and\n"
51
                                                   "hold MENU+SELECT to reboot.\n";
52
 
289 theseven 53
static uint16_t swapmap[RAMDISK_SECTORS] IBSS_ATTR;
54
static uint16_t swaprev[RAMDISK_SECTORS] IBSS_ATTR;
243 theseven 55
static char swapbuf[RAMDISK_SECTORSIZE];
289 theseven 56
static uint16_t newfat[RAMDISK_SECTORS] IBSS_ATTR;
243 theseven 57
static char newdir[RAMDISK_SECTORSIZE];
58
 
59
 
60
extern void* _ramdiskptr;
61
 
62
 
63
int fat16_calc_fatsectors(int sectors)
64
{
65
    uint32_t fatsectors = 1;
66
    uint32_t oldfatsectors = 0;
67
    uint32_t clustercount;
68
    while (fatsectors != oldfatsectors)
69
    {
70
        oldfatsectors = fatsectors;
71
        clustercount = sectors - fatsectors - 2;
72
        fatsectors = (2 * (clustercount + 2) + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
73
    }
74
    return fatsectors;
75
}
76
 
77
int fat16_write_mbr(uint8_t* buffer, int sectors)
78
{
79
    uint32_t fatsectors = fat16_calc_fatsectors(sectors);
80
    memset(buffer, 0, 0x800);
81
    memcpy(buffer, "\xeb\x58\x00MSWIN5.0\0\x08", 0xd);
82
    buffer[0xd] = 1;
83
    ((uint16_t*)buffer)[7] = 1;
84
    memcpy(&buffer[0x10], "\x01\x40\0\0\x40\xf8\0\0\x3f\0\xff", 0xb);
85
    buffer[0x13] = sectors & 0xff;
86
    buffer[0x14] = sectors >> 8;
87
    ((uint16_t*)buffer)[0xb] = fatsectors;
88
    buffer[0x24] = 0x80;
89
    buffer[0x26] = 0x29;
246 theseven 90
    memcpy(&buffer[0x27], "UBRDUMSboot    FAT16   ", 0x17);
243 theseven 91
    ((uint16_t*)buffer)[0xff] = 0xaa55;
92
    return fatsectors;
93
}
94
 
95
void fat16_write_fat(uint8_t* buffer, int sectors)
96
{
97
    memset(buffer, 0, sectors * RAMDISK_SECTORSIZE);
98
    *((uint32_t*)buffer) = 0xfffffff8;
99
}
100
 
101
void fat16_write_rootdir(uint8_t* buffer)
102
{
103
    memset(buffer, 0, RAMDISK_SECTORSIZE);
104
    memcpy(buffer, "UMSboot    \x08", 12);
105
}
106
 
107
void swap(src, dest)
108
{
247 theseven 109
    memcpy(swapbuf, ramdisk[dest], RAMDISK_SECTORSIZE);
243 theseven 110
    uint16_t srcmap = swapmap[src];
111
    uint16_t destmap = swaprev[dest];
112
    memcpy(ramdisk[dest], ramdisk[srcmap], RAMDISK_SECTORSIZE);
247 theseven 113
    swapmap[src] = dest;
114
    swaprev[dest] = src;
243 theseven 115
    memcpy(ramdisk[srcmap], swapbuf, RAMDISK_SECTORSIZE);
247 theseven 116
    swaprev[srcmap] = destmap;
243 theseven 117
    swapmap[destmap] = srcmap;
118
}
119
 
120
void main()
121
{
122
    int i;
123
    int fatsectors = fat16_write_mbr(ramdisk[0], RAMDISK_SECTORS);
124
    fat16_write_fat(ramdisk[1], fatsectors);
125
    fat16_write_rootdir(ramdisk[1 + fatsectors]);
126
    usb_init();
127
    for (i = 0; i < RAMDISK_SECTORS; i++) swapmap[i] = i;
128
    memcpy(swaprev, swapmap, sizeof(swaprev));
129
    while (!vbus_state());
130
    udelay(1000000);
131
    while (vbus_state() && !usb_ejected);
132
    udelay(200000);
133
    usb_exit();
421 theseven 134
    lcdconsole_puts("\nLoading UBI file...\n", LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
243 theseven 135
    int found = 0;
136
    uint16_t cluster;
137
    uint32_t size;
138
    uint16_t totalclusters = 0;
139
    for (i = 0; i < RAMDISK_SECTORSIZE; i += 32)
140
        if (!ramdisk[1 + fatsectors][i]) break;
141
        else if (ramdisk[1 + fatsectors][i] == 0xe5) continue;
142
        else if (((*((uint32_t*)&ramdisk[1 + fatsectors][i + 8])) & 0xffffff) == 0x494255)
143
        {
144
            cluster = *((uint16_t*)&ramdisk[1 + fatsectors][i + 26]);
145
            size = *((uint32_t*)&ramdisk[1 + fatsectors][i + 28]);
146
            ramdisk[1 + fatsectors][i] = 0xe5;
147
            found++;
148
        }
247 theseven 149
        else if (*((uint16_t*)&ramdisk[1 + fatsectors][i + 26]))
150
            totalclusters += (*((uint32_t*)&ramdisk[1 + fatsectors][i + 28])
151
                            + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
243 theseven 152
    if (!found)
153
    {
421 theseven 154
        lcdconsole_puts("No UBI file found!", LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
243 theseven 155
        return;
156
    }
157
    if (found != 1)
158
    {
421 theseven 159
        lcdconsole_puts("Multiple UBI files found!\nPlease copy exactly one.", LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
243 theseven 160
        return;
161
    }
162
    if (!size || !cluster)
163
    {
421 theseven 164
        lcdconsole_puts("UBI file is empty!", LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
243 theseven 165
        return;
166
    }
167
    uint16_t dest = 0;
168
    while (cluster != 0xffff)
169
    {
170
        swap(fatsectors + cluster, dest++);
246 theseven 171
        cluster = *((uint16_t*)&ramdisk[swapmap[1 + (cluster / (RAMDISK_SECTORSIZE / 2))]]
172
                                       [(cluster % (RAMDISK_SECTORSIZE / 2)) * 2]); 
243 theseven 173
    }
421 theseven 174
    lcdconsole_puts("Rearranging files...\n", LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
243 theseven 175
    uint16_t offset = RAMDISK_SECTORS - totalclusters - 2;
176
    memset(newfat, 0, sizeof(newfat));
177
    memset(newdir, 0, sizeof(newdir));
178
    *((uint32_t*)newfat) = *((uint32_t*)ramdisk[swapmap[1]]);
179
    dest = 2;
180
    int newptr = 0;
181
    for (i = 0; i < RAMDISK_SECTORSIZE; i += 32)
182
        if (!ramdisk[swapmap[1 + fatsectors]][i]) break;
183
        else if (ramdisk[swapmap[1 + fatsectors]][i] == 0xe5) continue;
184
        else
185
        {
186
            memcpy(&newdir[newptr], &ramdisk[swapmap[1 + fatsectors]][i], 0x20);
187
            cluster = *((uint16_t*)&newdir[newptr + 26]);
188
            size = *((uint32_t*)&newdir[newptr + 28]);
189
            if (cluster)
190
            {
191
                *((uint16_t*)&newdir[newptr + 26]) = dest;
192
                while (cluster != 0xffff)
193
                {
194
                    swap(fatsectors + cluster, offset + dest++);
246 theseven 195
                    cluster = *((uint16_t*)&ramdisk[swapmap[1 + (cluster / (RAMDISK_SECTORSIZE / 2))]]
196
                                                   [(cluster % (RAMDISK_SECTORSIZE / 2)) * 2]);
197
                    if (cluster == 0xffff) newfat[dest - 1] = 0xffff;
198
                    else newfat[dest - 1] = dest;
243 theseven 199
                }
200
            }
201
            newptr += 0x20;
202
        }
203
    fatsectors = (2 * (totalclusters + 2) + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
204
    _ramdiskptr = ramdisk[offset - fatsectors];
205
    memcpy(ramdisk[offset + 1], newdir, RAMDISK_SECTORSIZE);
206
    memcpy(ramdisk[offset - fatsectors + 1], newfat, fatsectors * RAMDISK_SECTORSIZE);
207
    fat16_write_mbr(_ramdiskptr, totalclusters + fatsectors + 2);
421 theseven 208
    lcdconsole_puts("Booting...", LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
289 theseven 209
    displaylcd_sync();
373 theseven 210
    udelay(10000);
243 theseven 211
    execfirmware(ramdisk[0]);
212
}
213
 
214
void init() INITCODE_ATTR;
215
void init()
216
{
217
#ifdef HAVE_TARGETINIT_VERYEARLY
218
    targetinit_veryearly();
219
#endif
740 theseven 220
    interrupt_init();
243 theseven 221
#ifdef HAVE_LCD
222
    lcd_init();
223
    lcdconsole_init();
224
#endif
225
#ifdef HAVE_TARGETINIT_EARLY
226
    targetinit_early();
227
#endif
228
#ifdef HAVE_I2C
229
    i2c_init();
230
#endif
231
    power_init();
421 theseven 232
    lcdconsole_puts(welcomestring, LCDCONSOLE_FGCOLOR, LCDCONSOLE_BGCOLOR);
243 theseven 233
#ifdef HAVE_BACKLIGHT
234
    backlight_init();
235
#endif
236
#ifdef HAVE_TARGETINIT_LATE
237
    targetinit_late();
238
#endif
239
}