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
 
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();
247 theseven 134
    lcdconsole_puts("\nLoading UBI file...\n", 0, 0xffff);
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
    {
154
        lcdconsole_puts("No UBI file found!", 0, 0xffff);
155
        return;
156
    }
157
    if (found != 1)
158
    {
159
        lcdconsole_puts("Multiple UBI files found!\nPlease copy exactly one.", 0, 0xffff);
160
        return;
161
    }
162
    if (!size || !cluster)
163
    {
164
        lcdconsole_puts("UBI file is empty!", 0, 0xffff);
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
    }
174
    lcdconsole_puts("Rearranging files...\n", 0, 0xffff);
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);
208
    lcdconsole_puts("Booting...", 0, 0xffff);
289 theseven 209
    displaylcd_sync();
243 theseven 210
    execfirmware(ramdisk[0]);
211
}
212
 
213
void init() INITCODE_ATTR;
214
void init()
215
{
216
#ifdef HAVE_TARGETINIT_VERYEARLY
217
    targetinit_veryearly();
218
#endif
219
#ifdef HAVE_LCD
220
    lcd_init();
221
    lcdconsole_init();
222
#endif
223
#ifdef HAVE_TARGETINIT_EARLY
224
    targetinit_early();
225
#endif
226
    interrupt_init();
227
#ifdef HAVE_I2C
228
    i2c_init();
229
#endif
230
    power_init();
231
    lcdconsole_puts(welcomestring, 0, 0xffff);
232
#ifdef HAVE_BACKLIGHT
233
    backlight_init();
234
#endif
235
#ifdef HAVE_TARGETINIT_LATE
236
    targetinit_late();
237
#endif
238
}