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";
429 theseven 78
static struct scheduler_thread initthread_handle INITBSS_ATTR;
89 theseven 79
static uint32_t initstack[0x400] INITSTACK_ATTR;
80
extern int _loadspaceend;
249 theseven 81
#ifdef HAVE_STORAGE
82
static const char storageinitthreadname[] INITCONST_ATTR = "Storage init thread";
429 theseven 83
static struct scheduler_thread storageinitthread_handle INITBSS_ATTR;
249 theseven 84
static uint32_t storageinitstack[0x400] INITBSS_ATTR;
85
static struct wakeup storageinitwakeup;
86
#endif
98 theseven 87
struct bootinfo_t bootinfo_src INITHEAD_ATTR =
89 theseven 88
{
429 theseven 89
    .signature = "emCOboot",
89 theseven 90
    .version = 0,
91
    .trydataflash = false,
92
    .trybootflash = false,
93
    .trymemmapped = false
94
};
15 theseven 95
 
87 theseven 96
 
89 theseven 97
void boot()
98
{
99
    struct bootinfo_t bootinfo = bootinfo_src;
100
#ifdef HAVE_STORAGE
101
    if (bootinfo.trydataflash)
102
    {
103
        int fd = file_open(bootinfo.dataflashpath, O_RDONLY);
104
        if (fd < 0) goto dataflashfailed;
95 theseven 105
        int size = filesize(fd);
106
        if (size < 0) goto dataflashfailed;
89 theseven 107
        if (bootinfo.dataflashflags & 1)
108
        {
109
            void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1));
110
            if (read(fd, addr, size) != size) goto dataflashfailed;
140 theseven 111
            if (ucl_decompress(addr, size, bootinfo.dataflashdest, (uint32_t*)&size))
112
                goto dataflashfailed;
89 theseven 113
        }
140 theseven 114
        else if (read(fd, bootinfo.dataflashdest, size) != size) goto dataflashfailed;
115
        if (execimage(bootinfo.dataflashdest) >= 0) return;
89 theseven 116
    }
117
dataflashfailed:
118
#endif
119
#ifdef HAVE_BOOTFLASH
120
    if (bootinfo.trybootflash)
121
    {
95 theseven 122
        int size = bootflash_filesize(bootinfo.bootimagename);
89 theseven 123
        if (size < 0) goto bootflashfailed;
124
#ifdef BOOTFLASH_IS_MEMMAPPED
125
        void* addr = bootflash_getaddr(bootinfo.bootimagename);
95 theseven 126
        if (!addr) goto bootflashfailed;
89 theseven 127
        if (bootinfo.bootflashflags & 1)
128
        {
140 theseven 129
            if (ucl_decompress(addr, size, bootinfo.bootflashdest, (uint32_t*)&size))
130
                goto bootflashfailed;
131
            if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 132
        }
133
        else if (bootinfo.bootflashflags & 2)
134
        {
140 theseven 135
            memcpy(bootinfo.bootflashdest, addr, size);
136
            if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 137
        }
133 theseven 138
        else if (execimage(addr) >= 0) return;
89 theseven 139
#else
140
        if (bootinfo.bootflashflags & 1)
141
        {
142
            void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1));
95 theseven 143
            if (bootflash_read(bootinfo.bootimagename, addr, 0, size) != size)
144
                goto bootflashfailed;
140 theseven 145
            if (ucl_decompress(addr, size, bootinfo.bootflashdest, (uint32_t*)&size))
146
                goto bootflashfailed;
89 theseven 147
        }
140 theseven 148
        else if (bootflash_read(bootinfo.bootimagename, bootinfo.bootflashdest, 0, size) != size)
95 theseven 149
            goto bootflashfailed;
140 theseven 150
        if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 151
#endif
152
    }
153
bootflashfailed:
154
#endif
155
    if (bootinfo.trymemmapped)
156
    {
95 theseven 157
        int size = bootinfo.memmappedsize;
133 theseven 158
        if (bootinfo.memmappedflags & 1)
89 theseven 159
        {
140 theseven 160
            if (ucl_decompress(bootinfo.memmappedaddr, size,
161
                               bootinfo.memmappeddest, (uint32_t*)&size))
89 theseven 162
                goto memmappedfailed;
140 theseven 163
            if (execimage(bootinfo.memmappeddest) >= 0) return;
89 theseven 164
        }
133 theseven 165
        else if (bootinfo.memmappedflags & 2)
89 theseven 166
        {
140 theseven 167
            memcpy(bootinfo.memmappeddest, bootinfo.memmappedaddr, size);
168
            if (execimage(bootinfo.memmappeddest) >= 0) return;
89 theseven 169
        }
133 theseven 170
        else if (execimage(bootinfo.memmappedaddr) >= 0) return;
89 theseven 171
    }
172
memmappedfailed:
173
    if (bootinfo.trydataflash || bootinfo.trybootflash || bootinfo.trymemmapped)
174
        cputs(CONSOLE_BOOT, "Could not find a usable boot image!\n");
175
    cputs(CONSOLE_BOOT, "Waiting for USB commands\n\n");
176
}
177
 
249 theseven 178
#ifdef HAVE_STORAGE
179
void storageinitthread() INITCODE_ATTR;
180
void storageinitthread()
181
{
182
    DEBUGF("Initializing storage drivers...");
183
    storage_init();
184
    DEBUGF("Initializing storage subsystem...");
185
    disk_init_subsystem();
186
    DEBUGF("Reading partition tables...");
187
    disk_init();
188
    DEBUGF("Mounting partitions...");
189
    disk_mount_all();
190
    DEBUGF("Storage init finished.");
191
    wakeup_signal(&storageinitwakeup);
192
}
193
#endif
194
 
66 theseven 195
void initthread() INITCODE_ATTR;
196
void initthread()
2 theseven 197
{
126 theseven 198
#ifdef HAVE_I2C
15 theseven 199
    i2c_init();
126 theseven 200
#endif
54 theseven 201
    power_init();
249 theseven 202
    cputs(CONSOLE_BOOT, welcomestring);
203
#ifdef HAVE_STORAGE
204
    wakeup_init(&storageinitwakeup);
429 theseven 205
    thread_create(&storageinitthread_handle, storageinitthreadname,
206
                  storageinitthread, storageinitstack,
207
                  sizeof(storageinitstack), USER_THREAD, 127, true);
249 theseven 208
#endif
126 theseven 209
#ifdef HAVE_USB
15 theseven 210
    usb_init();
126 theseven 211
#endif
190 theseven 212
#ifdef HAVE_BACKLIGHT
213
    backlight_init();
214
#endif
130 theseven 215
#ifdef HAVE_BUTTON
216
    button_init();
217
#endif
126 theseven 218
#ifdef HAVE_TARGETINIT_LATE
219
    targetinit_late();
220
#endif
249 theseven 221
#ifdef HAVE_STORAGE
222
    while (true)
223
    {
224
        if (wakeup_wait(&storageinitwakeup, 100000) == THREAD_OK) break;
429 theseven 225
        enum thread_state state = thread_get_state(&storageinitthread_handle);
249 theseven 226
        if (state == THREAD_DEFUNCT || state == THREAD_DEFUNCT_ACK)
227
        {
228
            if (wakeup_wait(&storageinitwakeup, 0) == THREAD_OK) break;
429 theseven 229
            thread_terminate(&storageinitthread_handle);
249 theseven 230
            break;
231
        }
232
    }
233
#endif
234
#ifdef HAVE_TARGETINIT_VERYLATE
235
    targetinit_verylate();
236
#endif
66 theseven 237
    DEBUGF("Finished initialisation sequence");
89 theseven 238
    boot();
66 theseven 239
}
240
 
241
void init() INITCODE_ATTR;
242
void init()
243
{
126 theseven 244
#ifdef HAVE_TARGETINIT_VERYEARLY
245
    targetinit_veryearly();
246
#endif
66 theseven 247
    scheduler_init();
248
    console_init();
126 theseven 249
#ifdef HAVE_LCD
66 theseven 250
    lcd_init();
251
    lcdconsole_init();
126 theseven 252
#endif
253
#ifdef HAVE_TARGETINIT_EARLY
254
    targetinit_early();
255
#endif
66 theseven 256
    interrupt_init();
429 theseven 257
    thread_create(&initthread_handle, initthreadname, initthread, initstack,
66 theseven 258
                  sizeof(initstack), USER_THREAD, 127, true);
259
}