Subversion Repositories freemyipod

Rev

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

Rev Author Line No. Line
2 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
427 farthen 6
//    This file is part of emCORE.
2 theseven 7
//
427 farthen 8
//    emCORE is free software: you can redistribute it and/or
2 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
//
427 farthen 13
//    emCORE is distributed in the hope that it will be useful,
2 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
427 farthen 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
2 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
14 theseven 25
#include "thread.h"
26
#include "console.h"
85 theseven 27
#include "power.h"
28
#include "interrupt.h"
89 theseven 29
#include "ucl.h"
30
#include "util.h"
31
#include "execimage.h"
126 theseven 32
#include "targetinit.h"
85 theseven 33
#ifdef HAVE_LCD
15 theseven 34
#include "lcd.h"
2 theseven 35
#include "lcdconsole.h"
85 theseven 36
#endif
37
#ifdef HAVE_I2C
15 theseven 38
#include "i2c.h"
85 theseven 39
#endif
40
#ifdef HAVE_USB
41
#include "usb/usb.h"
42
#endif
43
#ifdef HAVE_STORAGE
58 theseven 44
#include "storage.h"
45
#include "disk.h"
89 theseven 46
#include "file.h"
85 theseven 47
#endif
95 theseven 48
#ifdef HAVE_BOOTFLASH
49
#include "bootflash.h"
50
#endif
191 theseven 51
#ifdef HAVE_BACKLIGHT
190 theseven 52
#include "backlight.h"
53
#endif
2 theseven 54
 
87 theseven 55
 
89 theseven 56
struct bootinfo_t
57
{
58
    char signature[8];
59
    int version;
60
    bool trydataflash;
61
    char dataflashpath[256];
62
    bool dataflashflags;
140 theseven 63
    void* dataflashdest;
89 theseven 64
    bool trybootflash;
65
    char bootimagename[8];
66
    bool bootflashflags;
140 theseven 67
    void* bootflashdest;
89 theseven 68
    bool trymemmapped;
69
    void* memmappedaddr;
95 theseven 70
    int memmappedsize;
89 theseven 71
    bool memmappedflags;
140 theseven 72
    void* memmappeddest;
89 theseven 73
};
74
 
75
 
427 farthen 76
static const char welcomestring[] INITCONST_ATTR = "emCORE v" VERSION " r" VERSION_SVN "\n\n";
110 theseven 77
static const char initthreadname[] INITCONST_ATTR = "Initialization thread";
89 theseven 78
static uint32_t initstack[0x400] INITSTACK_ATTR;
79
extern int _loadspaceend;
249 theseven 80
#ifdef HAVE_STORAGE
81
static const char storageinitthreadname[] INITCONST_ATTR = "Storage init thread";
82
static uint32_t storageinitstack[0x400] INITBSS_ATTR;
83
static struct wakeup storageinitwakeup;
84
#endif
98 theseven 85
struct bootinfo_t bootinfo_src INITHEAD_ATTR =
89 theseven 86
{
87
    .signature = "emBIboot",
88
    .version = 0,
89
    .trydataflash = false,
90
    .trybootflash = false,
91
    .trymemmapped = false
92
};
15 theseven 93
 
87 theseven 94
 
89 theseven 95
void boot()
96
{
97
    struct bootinfo_t bootinfo = bootinfo_src;
98
#ifdef HAVE_STORAGE
99
    if (bootinfo.trydataflash)
100
    {
101
        int fd = file_open(bootinfo.dataflashpath, O_RDONLY);
102
        if (fd < 0) goto dataflashfailed;
95 theseven 103
        int size = filesize(fd);
104
        if (size < 0) goto dataflashfailed;
89 theseven 105
        if (bootinfo.dataflashflags & 1)
106
        {
107
            void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1));
108
            if (read(fd, addr, size) != size) goto dataflashfailed;
140 theseven 109
            if (ucl_decompress(addr, size, bootinfo.dataflashdest, (uint32_t*)&size))
110
                goto dataflashfailed;
89 theseven 111
        }
140 theseven 112
        else if (read(fd, bootinfo.dataflashdest, size) != size) goto dataflashfailed;
113
        if (execimage(bootinfo.dataflashdest) >= 0) return;
89 theseven 114
    }
115
dataflashfailed:
116
#endif
117
#ifdef HAVE_BOOTFLASH
118
    if (bootinfo.trybootflash)
119
    {
95 theseven 120
        int size = bootflash_filesize(bootinfo.bootimagename);
89 theseven 121
        if (size < 0) goto bootflashfailed;
122
#ifdef BOOTFLASH_IS_MEMMAPPED
123
        void* addr = bootflash_getaddr(bootinfo.bootimagename);
95 theseven 124
        if (!addr) goto bootflashfailed;
89 theseven 125
        if (bootinfo.bootflashflags & 1)
126
        {
140 theseven 127
            if (ucl_decompress(addr, size, bootinfo.bootflashdest, (uint32_t*)&size))
128
                goto bootflashfailed;
129
            if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 130
        }
131
        else if (bootinfo.bootflashflags & 2)
132
        {
140 theseven 133
            memcpy(bootinfo.bootflashdest, addr, size);
134
            if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 135
        }
133 theseven 136
        else if (execimage(addr) >= 0) return;
89 theseven 137
#else
138
        if (bootinfo.bootflashflags & 1)
139
        {
140
            void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1));
95 theseven 141
            if (bootflash_read(bootinfo.bootimagename, addr, 0, size) != size)
142
                goto bootflashfailed;
140 theseven 143
            if (ucl_decompress(addr, size, bootinfo.bootflashdest, (uint32_t*)&size))
144
                goto bootflashfailed;
89 theseven 145
        }
140 theseven 146
        else if (bootflash_read(bootinfo.bootimagename, bootinfo.bootflashdest, 0, size) != size)
95 theseven 147
            goto bootflashfailed;
140 theseven 148
        if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 149
#endif
150
    }
151
bootflashfailed:
152
#endif
153
    if (bootinfo.trymemmapped)
154
    {
95 theseven 155
        int size = bootinfo.memmappedsize;
133 theseven 156
        if (bootinfo.memmappedflags & 1)
89 theseven 157
        {
140 theseven 158
            if (ucl_decompress(bootinfo.memmappedaddr, size,
159
                               bootinfo.memmappeddest, (uint32_t*)&size))
89 theseven 160
                goto memmappedfailed;
140 theseven 161
            if (execimage(bootinfo.memmappeddest) >= 0) return;
89 theseven 162
        }
133 theseven 163
        else if (bootinfo.memmappedflags & 2)
89 theseven 164
        {
140 theseven 165
            memcpy(bootinfo.memmappeddest, bootinfo.memmappedaddr, size);
166
            if (execimage(bootinfo.memmappeddest) >= 0) return;
89 theseven 167
        }
133 theseven 168
        else if (execimage(bootinfo.memmappedaddr) >= 0) return;
89 theseven 169
    }
170
memmappedfailed:
171
    if (bootinfo.trydataflash || bootinfo.trybootflash || bootinfo.trymemmapped)
172
        cputs(CONSOLE_BOOT, "Could not find a usable boot image!\n");
173
    cputs(CONSOLE_BOOT, "Waiting for USB commands\n\n");
174
}
175
 
249 theseven 176
#ifdef HAVE_STORAGE
177
void storageinitthread() INITCODE_ATTR;
178
void storageinitthread()
179
{
180
    DEBUGF("Initializing storage drivers...");
181
    storage_init();
182
    DEBUGF("Initializing storage subsystem...");
183
    disk_init_subsystem();
184
    DEBUGF("Reading partition tables...");
185
    disk_init();
186
    DEBUGF("Mounting partitions...");
187
    disk_mount_all();
188
    DEBUGF("Storage init finished.");
189
    wakeup_signal(&storageinitwakeup);
190
}
191
#endif
192
 
66 theseven 193
void initthread() INITCODE_ATTR;
194
void initthread()
2 theseven 195
{
126 theseven 196
#ifdef HAVE_I2C
15 theseven 197
    i2c_init();
126 theseven 198
#endif
54 theseven 199
    power_init();
249 theseven 200
    cputs(CONSOLE_BOOT, welcomestring);
201
#ifdef HAVE_STORAGE
202
    wakeup_init(&storageinitwakeup);
203
    int storagethread = thread_create(storageinitthreadname, storageinitthread, storageinitstack,
204
                                      sizeof(storageinitstack), USER_THREAD, 127, true);
205
#endif
126 theseven 206
#ifdef HAVE_USB
15 theseven 207
    usb_init();
126 theseven 208
#endif
190 theseven 209
#ifdef HAVE_BACKLIGHT
210
    backlight_init();
211
#endif
130 theseven 212
#ifdef HAVE_BUTTON
213
    button_init();
214
#endif
126 theseven 215
#ifdef HAVE_TARGETINIT_LATE
216
    targetinit_late();
217
#endif
249 theseven 218
#ifdef HAVE_STORAGE
219
    while (true)
220
    {
221
        if (wakeup_wait(&storageinitwakeup, 100000) == THREAD_OK) break;
222
        enum thread_state state = thread_get_state(storagethread);
223
        if (state == THREAD_DEFUNCT || state == THREAD_DEFUNCT_ACK)
224
        {
225
            if (wakeup_wait(&storageinitwakeup, 0) == THREAD_OK) break;
226
            thread_terminate(storagethread);
227
            break;
228
        }
229
    }
230
#endif
231
#ifdef HAVE_TARGETINIT_VERYLATE
232
    targetinit_verylate();
233
#endif
66 theseven 234
    DEBUGF("Finished initialisation sequence");
89 theseven 235
    boot();
66 theseven 236
}
237
 
238
void init() INITCODE_ATTR;
239
void init()
240
{
126 theseven 241
#ifdef HAVE_TARGETINIT_VERYEARLY
242
    targetinit_veryearly();
243
#endif
66 theseven 244
    scheduler_init();
245
    console_init();
126 theseven 246
#ifdef HAVE_LCD
66 theseven 247
    lcd_init();
248
    lcdconsole_init();
126 theseven 249
#endif
250
#ifdef HAVE_TARGETINIT_EARLY
251
    targetinit_early();
252
#endif
66 theseven 253
    interrupt_init();
254
    thread_create(initthreadname, initthread, initstack,
255
                  sizeof(initstack), USER_THREAD, 127, true);
256
}