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"
436 theseven 33
#include "malloc.h"
85 theseven 34
#ifdef HAVE_LCD
15 theseven 35
#include "lcd.h"
2 theseven 36
#include "lcdconsole.h"
85 theseven 37
#endif
38
#ifdef HAVE_I2C
15 theseven 39
#include "i2c.h"
85 theseven 40
#endif
41
#ifdef HAVE_USB
42
#include "usb/usb.h"
43
#endif
44
#ifdef HAVE_STORAGE
58 theseven 45
#include "storage.h"
46
#include "disk.h"
89 theseven 47
#include "file.h"
85 theseven 48
#endif
95 theseven 49
#ifdef HAVE_BOOTFLASH
50
#include "bootflash.h"
51
#endif
191 theseven 52
#ifdef HAVE_BACKLIGHT
190 theseven 53
#include "backlight.h"
54
#endif
2 theseven 55
 
87 theseven 56
 
436 theseven 57
extern int _poolstart;   // Not an int at all, but gcc complains about void types being
58
                         // used here, and we only need the address, so just make it happy...
59
 
60
 
61
enum boottype
89 theseven 62
{
436 theseven 63
    BOOTTYPE_PIGGYBACKED = 1,
64
    BOOTTYPE_BOOTFLASH = 2,
65
    BOOTTYPE_FILESYSTEM = 3
66
};
67
 
68
struct bootoption
69
{
70
    struct bootoption* next;
71
    enum boottype type;
72
    char* source;
73
};
74
 
75
struct bootinfo
76
{
89 theseven 77
    char signature[8];
78
    int version;
436 theseven 79
    void* baseaddr;
80
    size_t totalsize;
81
    struct bootoption* options;
89 theseven 82
};
83
 
84
 
436 theseven 85
struct initbss
86
{
87
    struct scheduler_thread initthread;
88
    uint32_t initstack[0x400];
89
#ifdef HAVE_STORAGE
90
    struct scheduler_thread storagethread;
91
    uint32_t storagestack[0x400];
92
    struct wakeup storagewakeup;
93
#endif
94
};
95
 
96
 
97
static struct initbss* ib INITDATA_ATTR = NULL;
427 farthen 98
static const char welcomestring[] INITCONST_ATTR = "emCORE v" VERSION " r" VERSION_SVN "\n\n";
110 theseven 99
static const char initthreadname[] INITCONST_ATTR = "Initialization thread";
436 theseven 100
static const char unknownboottypestr[] INITCONST_ATTR = "Skipping boot option with unknown type %d\n";
101
static const char nobootoptionsstr[] INITCONST_ATTR = "No usable boot options, waiting for USB commands\n\n";
249 theseven 102
#ifdef HAVE_STORAGE
436 theseven 103
static const char storagethreadname[] INITCONST_ATTR = "Storage init thread";
249 theseven 104
#endif
436 theseven 105
 
106
struct bootinfo bootinfo INITTAIL_ATTR =
89 theseven 107
{
429 theseven 108
    .signature = "emCOboot",
436 theseven 109
    .version = 1,
110
    .baseaddr = &bootinfo,
111
    .totalsize = sizeof(struct bootinfo),
112
    .options = NULL
89 theseven 113
};
15 theseven 114
 
87 theseven 115
 
89 theseven 116
#ifdef HAVE_STORAGE
249 theseven 117
void storageinitthread() INITCODE_ATTR;
118
void storageinitthread()
119
{
120
    DEBUGF("Initializing storage drivers...");
121
    storage_init();
122
    DEBUGF("Initializing storage subsystem...");
123
    disk_init_subsystem();
124
    DEBUGF("Reading partition tables...");
125
    disk_init();
126
    DEBUGF("Mounting partitions...");
127
    disk_mount_all();
128
    DEBUGF("Storage init finished.");
436 theseven 129
    wakeup_signal(&(ib->storagewakeup));
249 theseven 130
}
131
#endif
132
 
66 theseven 133
void initthread() INITCODE_ATTR;
134
void initthread()
2 theseven 135
{
126 theseven 136
#ifdef HAVE_I2C
15 theseven 137
    i2c_init();
126 theseven 138
#endif
54 theseven 139
    power_init();
249 theseven 140
    cputs(CONSOLE_BOOT, welcomestring);
141
#ifdef HAVE_STORAGE
436 theseven 142
    wakeup_init(&(ib->storagewakeup));
143
    thread_create(&(ib->storagethread), storagethreadname, storageinitthread,
144
                  ib->storagestack, sizeof(ib->storagestack), USER_THREAD, 127, true);
249 theseven 145
#endif
126 theseven 146
#ifdef HAVE_USB
15 theseven 147
    usb_init();
126 theseven 148
#endif
190 theseven 149
#ifdef HAVE_BACKLIGHT
150
    backlight_init();
151
#endif
130 theseven 152
#ifdef HAVE_BUTTON
153
    button_init();
154
#endif
126 theseven 155
#ifdef HAVE_TARGETINIT_LATE
156
    targetinit_late();
157
#endif
249 theseven 158
#ifdef HAVE_STORAGE
159
    while (true)
160
    {
436 theseven 161
        if (wakeup_wait(&(ib->storagewakeup), 100000) == THREAD_OK) break;
162
        enum thread_state state = thread_get_state(&(ib->storagethread));
163
        if (state == THREAD_DEFUNCT_ACK)
249 theseven 164
        {
436 theseven 165
            if (wakeup_wait(&(ib->storagewakeup), 0) == THREAD_OK) break;
166
            thread_terminate(&(ib->storagethread));
249 theseven 167
            break;
168
        }
169
    }
170
#endif
171
#ifdef HAVE_TARGETINIT_VERYLATE
172
    targetinit_verylate();
173
#endif
66 theseven 174
    DEBUGF("Finished initialisation sequence");
436 theseven 175
 
176
    struct bootoption* option;
177
    bool done = false;
178
    for (option = bootinfo.options; !done && option; option = option->next)
179
        switch (option->type)
180
        {
181
        case BOOTTYPE_PIGGYBACKED:
182
            done = execimage(option->source, true) > 0;
183
            break;
184
 
185
#ifdef HAVE_BOOTFLASH
186
        case BOOTTYPE_BOOTFLASH:
187
        {
188
            int size = bootflash_filesize(option->source);
189
            if (size <= 0) break;
190
            void* buffer = memalign(0x10, size);
191
            if (!buffer) break;
192
            if (bootflash_read(option->source, buffer, 0, size) != size)
193
            {
194
                free(buffer);
195
                break;
196
            }
197
            done = execimage(buffer, false);
198
            if (!done) free(buffer);
199
            break;
200
        }
201
#endif
202
 
203
#ifdef HAVE_STORAGE
204
        case BOOTTYPE_FILESYSTEM:
205
        {
206
            int fd = file_open(option->source, O_RDONLY);
207
            if (fd <= 0) break;
208
            int size = filesize(fd);
209
            if (size <= 0)
210
            {
211
                close(fd);
212
                break;
213
            }
214
            void* buffer = memalign(0x10, size);
215
            if (!buffer)
216
            {
217
                close(fd);
218
                break;
219
            }
220
            if (read(fd, buffer, size) != size)
221
            {
222
                free(buffer);
223
                close(fd);
224
                break;
225
            }
226
            close(fd);
227
            done = execimage(buffer, false);
228
            if (!done) free(buffer);
229
            break;
230
        }
231
#endif
232
 
233
        default:
234
            cprintf(CONSOLE_BOOT, unknownboottypestr, option->type);
235
        }
236
    cputs(CONSOLE_BOOT, nobootoptionsstr);
66 theseven 237
}
238
 
239
void init() INITCODE_ATTR;
240
void init()
241
{
126 theseven 242
#ifdef HAVE_TARGETINIT_VERYEARLY
243
    targetinit_veryearly();
244
#endif
66 theseven 245
    scheduler_init();
246
    console_init();
126 theseven 247
#ifdef HAVE_LCD
66 theseven 248
    lcd_init();
249
    lcdconsole_init();
126 theseven 250
#endif
251
#ifdef HAVE_TARGETINIT_EARLY
252
    targetinit_early();
253
#endif
66 theseven 254
    interrupt_init();
436 theseven 255
    malloc_init();
256
    size_t size = (size_t)(&bootinfo) - (size_t)(&_poolstart) + bootinfo.totalsize;
257
    void* bootalloc = malloc(size);
258
    size -= (size_t)(bootalloc) - (size_t)(&_poolstart);
259
    realloc(bootalloc, size);
260
    ib = (struct initbss*)malloc(sizeof(struct initbss));
261
    reownalloc(ib, &(ib->initthread));
262
    reownalloc(bootalloc, &(ib->initthread));
263
    thread_create(&(ib->initthread), initthreadname, initthread, ib->initstack,
264
                  sizeof(ib->initstack), USER_THREAD, 127, true);
66 theseven 265
}