Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
881 theseven 1
#include "global.h"
2
#include "app/umsboot/main.h"
3
#include "app/main.h"
4
#include "app/umsboot/usbglue.h"
5
#include "app/umsboot/ums.h"
6
#include "sys/time.h"
7
#include "sys/util.h"
8
#include "protocol/usb/usb.h"
9
 
10
#ifdef UMSBOOT_HAVE_CONSOLE
11
#include "interface/console/console.h"
12
#include "app/umsboot/console.h"
13
#endif
14
 
15
 
16
static uint16_t swapmap[RAMDISK_SECTORS] __attribute__((aligned(CACHEALIGN_SIZE)));
17
static uint16_t swaprev[RAMDISK_SECTORS] __attribute__((aligned(CACHEALIGN_SIZE)));
18
static char swapbuf[RAMDISK_SECTORSIZE] __attribute__((aligned(CACHEALIGN_SIZE)));
19
static uint16_t newfat[RAMDISK_SECTORS] __attribute__((aligned(CACHEALIGN_SIZE)));
20
static char newdir[RAMDISK_SECTORSIZE] __attribute__((aligned(CACHEALIGN_SIZE)));
21
static int fatsectors;
22
 
23
 
24
int fat16_calc_fatsectors(int sectors)
25
{
26
    uint32_t fatsectors = 1;
27
    uint32_t oldfatsectors = 0;
28
    uint32_t clustercount;
29
    while (fatsectors != oldfatsectors)
30
    {
31
        oldfatsectors = fatsectors;
32
        clustercount = sectors - fatsectors - 2;
33
        fatsectors = (2 * (clustercount + 2) + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
34
    }
35
    return fatsectors;
36
}
37
 
38
int fat16_write_mbr(uint8_t* buffer, int sectors)
39
{
40
    uint32_t fatsectors = fat16_calc_fatsectors(sectors);
41
    memset(buffer, 0, RAMDISK_SECTORSIZE);
42
    memcpy(buffer, "\xeb\x58\x00MSWIN5.0", 0xb);
43
    buffer[0xb] = RAMDISK_SECTORSIZE & 0xff;
44
    buffer[0xc] = RAMDISK_SECTORSIZE >> 8;
45
    buffer[0xd] = 1;
46
    ((uint16_t*)buffer)[7] = 1;
47
    buffer[0x10] = 1;
48
    buffer[0x11] = (RAMDISK_SECTORSIZE >> 5) & 0xff;
49
    buffer[0x12] = RAMDISK_SECTORSIZE >> 13;
50
    buffer[0x13] = sectors & 0xff;
51
    buffer[0x14] = sectors >> 8;
52
    buffer[0x15] = 0xf8;
53
    buffer[0x18] = 0x3f;
54
    buffer[0x1a] = 0xff;
55
    ((uint16_t*)buffer)[0xb] = fatsectors;
56
    memcpy(&buffer[0x24], "\x80\0\x29UBRDUMSboot    FAT16   ", 0x1a);
57
    ((uint16_t*)buffer)[0xff] = 0xaa55;
58
    return fatsectors;
59
}
60
 
61
void fat16_write_fat(uint8_t* buffer, int sectors)
62
{
63
    memset(buffer, 0, sectors * RAMDISK_SECTORSIZE);
64
    *((uint32_t*)buffer) = 0xfffffff8;
65
}
66
 
67
void fat16_write_rootdir(uint8_t* buffer)
68
{
69
    memset(buffer, 0, RAMDISK_SECTORSIZE);
70
    memcpy(buffer, "UMSboot    \x08", 12);
71
}
72
 
73
void swap(src, dest)
74
{
75
    memcpy(swapbuf, RAMDISK[dest], RAMDISK_SECTORSIZE);
76
    uint16_t srcmap = swapmap[src];
77
    uint16_t destmap = swaprev[dest];
78
    memcpy(RAMDISK[dest], RAMDISK[srcmap], RAMDISK_SECTORSIZE);
79
    swapmap[src] = dest;
80
    swaprev[dest] = src;
81
    memcpy(RAMDISK[srcmap], swapbuf, RAMDISK_SECTORSIZE);
82
    swaprev[srcmap] = destmap;
83
    swapmap[destmap] = srcmap;
84
}
85
 
86
int main()
87
{
88
    int i;
89
#ifdef UMSBOOT_HAVE_CONSOLE
90
    umsboot_console_init();
91
#endif
92
    fatsectors = fat16_write_mbr(RAMDISK[0], RAMDISK_SECTORS);
93
    fat16_write_fat(RAMDISK[1], fatsectors);
94
    fat16_write_rootdir(RAMDISK[1 + fatsectors]);
95
    for (i = 0; i < RAMDISK_SECTORS; i++) swapmap[i] = i;
96
    memcpy(swaprev, swapmap, sizeof(swaprev));
97
    while (true)
98
    {
99
        ums_ejected = false;
100
        usb_init(&usb_data);
101
        while (!ums_ejected) idle();
102
        udelay(100000);
103
        usb_exit(&usb_data);
104
#ifdef UMSBOOT_HAVE_CONSOLE
105
        console_puts(&umsboot_console, "\nLoading UBI file...\n");
106
        console_flush(&umsboot_console);
107
#endif
108
        int found = 0;
109
        uint16_t cluster = 0;
110
        uint32_t size = 0;
111
        uint16_t totalclusters = 0;
112
        for (i = 0; i < RAMDISK_SECTORSIZE; i += 32)
113
            if (!RAMDISK[1 + fatsectors][i]) break;
114
            else if (RAMDISK[1 + fatsectors][i] == 0xe5) continue;
115
            else if (((((uint32_t*)RAMDISK[1 + fatsectors])[(i + 8) >> 2]) & 0xffffff) == 0x494255)
116
            {
117
                cluster = ((uint16_t*)RAMDISK[1 + fatsectors])[(i + 26) >> 1];
118
                size = ((uint32_t*)RAMDISK[1 + fatsectors])[(i + 28) >> 2];
119
                RAMDISK[1 + fatsectors][i] = 0xe5;
120
                found++;
121
            }
122
            else if (((uint16_t*)RAMDISK[1 + fatsectors])[(i + 26) >> 1])
123
                totalclusters += (((uint32_t*)RAMDISK[1 + fatsectors])[(i + 28) >> 2]
124
                                + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
125
        if (!found)
126
        {
127
#ifdef UMSBOOT_HAVE_CONSOLE
128
            console_puts(&umsboot_console, "No UBI file found!\nPlease retry.\n");
129
            console_flush(&umsboot_console);
130
#endif
131
            continue;
132
        }
133
        if (found != 1)
134
        {
135
#ifdef UMSBOOT_HAVE_CONSOLE
136
            console_puts(&umsboot_console, "Multiple UBI files found!\nPlease copy exactly one.\nPlease retry.\n");
137
            console_flush(&umsboot_console);
138
#endif
139
            continue;
140
        }
141
        if (!size || !cluster)
142
        {
143
#ifdef UMSBOOT_HAVE_CONSOLE
144
            console_puts(&umsboot_console, "UBI file is empty!\nPlease retry.\n");
145
            console_flush(&umsboot_console);
146
#endif
147
            continue;
148
        }
149
        uint16_t dest = 0;
150
        while (cluster != 0xffff)
151
        {
152
            swap(fatsectors + cluster, dest++);
153
            cluster = ((uint16_t*)RAMDISK[swapmap[1 + (cluster / (RAMDISK_SECTORSIZE / 2))]])
154
                                         [cluster % (RAMDISK_SECTORSIZE / 2)];
155
        }
156
#ifdef UMSBOOT_HAVE_CONSOLE
157
        console_puts(&umsboot_console, "Rearranging files...\n");
158
        console_flush(&umsboot_console);
159
#endif
160
        uint16_t offset = RAMDISK_SECTORS - totalclusters - 2;
161
        memset(newfat, 0, sizeof(newfat));
162
        memset(newdir, 0, sizeof(newdir));
163
        newfat[0] = ((uint16_t*)RAMDISK[swapmap[1]])[0];
164
        newfat[1] = ((uint16_t*)RAMDISK[swapmap[1]])[1];
165
        dest = 2;
166
        int newptr = 0;
167
        for (i = 0; i < RAMDISK_SECTORSIZE; i += 32)
168
            if (!RAMDISK[swapmap[1 + fatsectors]][i]) break;
169
            else if (RAMDISK[swapmap[1 + fatsectors]][i] == 0xe5) continue;
170
            else
171
            {
172
                memcpy(&newdir[newptr], &RAMDISK[swapmap[1 + fatsectors]][i], 0x20);
173
                cluster = ((uint16_t*)newdir)[(newptr + 26) >> 1];
174
                size = ((uint32_t*)newdir)[(newptr + 28) >> 2];
175
                if (cluster)
176
                {
177
                    ((uint16_t*)newdir)[(newptr + 26) >> 1] = dest;
178
                    while (cluster != 0xffff)
179
                    {
180
                        swap(fatsectors + cluster, offset + dest++);
181
                        cluster = ((uint16_t*)RAMDISK[swapmap[1 + (cluster / (RAMDISK_SECTORSIZE / 2))]])
182
                                                     [cluster % (RAMDISK_SECTORSIZE / 2)];
183
                        if (cluster == 0xffff) newfat[dest - 1] = 0xffff;
184
                        else newfat[dest - 1] = dest;
185
                    }
186
                }
187
                newptr += 0x20;
188
            }
189
        fatsectors = (2 * (totalclusters + 2) + RAMDISK_SECTORSIZE - 1) / RAMDISK_SECTORSIZE;
190
        RAMDISK_PTR = RAMDISK[offset - fatsectors];
191
        memcpy(RAMDISK[offset + 1], newdir, RAMDISK_SECTORSIZE);
192
        memcpy(RAMDISK[offset - fatsectors + 1], newfat, fatsectors * RAMDISK_SECTORSIZE);
193
        fat16_write_mbr(RAMDISK_PTR, totalclusters + fatsectors + 2);
194
#ifdef UMSBOOT_HAVE_CONSOLE
195
        console_puts(&umsboot_console, "Booting UBI file...");
196
        console_flush(&umsboot_console);
197
#endif
198
        execfirmware(RAMDISK[0]);
199
    }
200
}