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
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS is free software: you can redistribute it and/or
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
//
13
//    emBIOS is distributed in the hope that it will be useful,
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
19
//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
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
 
53
static uint16_t swapmap[RAMDISK_SECTORS];
54
static uint16_t swaprev[RAMDISK_SECTORS];
55
static char swapbuf[RAMDISK_SECTORSIZE];
56
static uint16_t newfat[RAMDISK_SECTORS];
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;
90
    memcpy(&buffer[0x27], "UMSbUMSboot    FAT16   ", 0x17);
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
{
109
    uint16_t srcmap = swapmap[src];
110
    uint16_t destmap = swaprev[dest];
111
    memcpy(swapbuf, ramdisk[dest], RAMDISK_SECTORSIZE);
112
    memcpy(ramdisk[dest], ramdisk[srcmap], RAMDISK_SECTORSIZE);
113
    memcpy(ramdisk[srcmap], swapbuf, RAMDISK_SECTORSIZE);
114
    swapmap[src] = dest;
115
    swapmap[destmap] = srcmap;
116
    swaprev[srcmap] = destmap;
117
    swaprev[dest] = src;
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();
134
    lcdconsole_puts("\nLoading UBI File...\n", 0, 0xffff);
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
        }
149
        else totalclusters += (*((uint32_t*)&ramdisk[1 + fatsectors][i + 28])
150
                             + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
151
    if (!found)
152
    {
153
        lcdconsole_puts("No UBI file found!", 0, 0xffff);
154
        return;
155
    }
156
    if (found != 1)
157
    {
158
        lcdconsole_puts("Multiple UBI files found!\nPlease copy exactly one.", 0, 0xffff);
159
        return;
160
    }
161
    if (!size || !cluster)
162
    {
163
        lcdconsole_puts("UBI file is empty!", 0, 0xffff);
164
        return;
165
    }
166
    uint16_t dest = 0;
167
    while (cluster != 0xffff)
168
    {
169
        swap(fatsectors + cluster, dest++);
170
        cluster = *((uint16_t*)&ramdisk[swapmap[1 + (cluster / RAMDISK_SECTORSIZE)]]
171
                                       [(cluster % RAMDISK_SECTORSIZE) * 2]); 
172
    }
173
    lcdconsole_puts("Rearranging files...\n", 0, 0xffff);
174
    uint16_t offset = RAMDISK_SECTORS - totalclusters - 2;
175
    memset(newfat, 0, sizeof(newfat));
176
    memset(newdir, 0, sizeof(newdir));
177
    *((uint32_t*)newfat) = *((uint32_t*)ramdisk[swapmap[1]]);
178
    dest = 2;
179
    int newptr = 0;
180
    for (i = 0; i < RAMDISK_SECTORSIZE; i += 32)
181
        if (!ramdisk[swapmap[1 + fatsectors]][i]) break;
182
        else if (ramdisk[swapmap[1 + fatsectors]][i] == 0xe5) continue;
183
        else
184
        {
185
            memcpy(&newdir[newptr], &ramdisk[swapmap[1 + fatsectors]][i], 0x20);
186
            cluster = *((uint16_t*)&newdir[newptr + 26]);
187
            size = *((uint32_t*)&newdir[newptr + 28]);
188
            if (cluster)
189
            {
190
                *((uint16_t*)&newdir[newptr + 26]) = dest;
191
                while (cluster != 0xffff)
192
                {
193
                    swap(fatsectors + cluster, offset + dest++);
194
                    cluster = *((uint16_t*)&ramdisk[swapmap[1 + (cluster / RAMDISK_SECTORSIZE)]]
195
                                                   [(cluster % RAMDISK_SECTORSIZE) * 2]);
196
                    if (cluster == 0xffff) ((uint16_t*)newfat)[dest - 1] = 0xffff;
197
                    else ((uint16_t*)newfat)[dest - 1] = dest;
198
                }
199
            }
200
            newptr += 0x20;
201
        }
202
    fatsectors = (2 * (totalclusters + 2) + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
203
    _ramdiskptr = ramdisk[offset - fatsectors];
204
    memcpy(ramdisk[offset + 1], newdir, RAMDISK_SECTORSIZE);
205
    memcpy(ramdisk[offset - fatsectors + 1], newfat, fatsectors * RAMDISK_SECTORSIZE);
206
    fat16_write_mbr(_ramdiskptr, totalclusters + fatsectors + 2);
207
    lcdconsole_puts("Booting...", 0, 0xffff);
208
    execfirmware(ramdisk[0]);
209
}
210
 
211
void init() INITCODE_ATTR;
212
void init()
213
{
214
#ifdef HAVE_TARGETINIT_VERYEARLY
215
    targetinit_veryearly();
216
#endif
217
#ifdef HAVE_LCD
218
    lcd_init();
219
    lcdconsole_init();
220
#endif
221
#ifdef HAVE_TARGETINIT_EARLY
222
    targetinit_early();
223
#endif
224
    interrupt_init();
225
#ifdef HAVE_I2C
226
    i2c_init();
227
#endif
228
    power_init();
229
    lcdconsole_puts(welcomestring, 0, 0xffff);
230
#ifdef HAVE_BACKLIGHT
231
    backlight_init();
232
#endif
233
#ifdef HAVE_TARGETINIT_LATE
234
    targetinit_late();
235
#endif
236
}