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];
437 theseven 89
    void* bootalloc;
436 theseven 90
#ifdef HAVE_STORAGE
91
    struct scheduler_thread storagethread;
92
    uint32_t storagestack[0x400];
93
    struct wakeup storagewakeup;
94
#endif
95
};
96
 
97
 
98
static struct initbss* ib INITDATA_ATTR = NULL;
427 farthen 99
static const char welcomestring[] INITCONST_ATTR = "emCORE v" VERSION " r" VERSION_SVN "\n\n";
110 theseven 100
static const char initthreadname[] INITCONST_ATTR = "Initialization thread";
436 theseven 101
static const char unknownboottypestr[] INITCONST_ATTR = "Skipping boot option with unknown type %d\n";
102
static const char nobootoptionsstr[] INITCONST_ATTR = "No usable boot options, waiting for USB commands\n\n";
249 theseven 103
#ifdef HAVE_STORAGE
436 theseven 104
static const char storagethreadname[] INITCONST_ATTR = "Storage init thread";
249 theseven 105
#endif
436 theseven 106
 
107
struct bootinfo bootinfo INITTAIL_ATTR =
89 theseven 108
{
429 theseven 109
    .signature = "emCOboot",
436 theseven 110
    .version = 1,
111
    .baseaddr = &bootinfo,
112
    .totalsize = sizeof(struct bootinfo),
113
    .options = NULL
89 theseven 114
};
15 theseven 115
 
87 theseven 116
 
89 theseven 117
#ifdef HAVE_STORAGE
249 theseven 118
void storageinitthread() INITCODE_ATTR;
119
void storageinitthread()
120
{
121
    DEBUGF("Initializing storage drivers...");
122
    storage_init();
123
    DEBUGF("Initializing storage subsystem...");
124
    disk_init_subsystem();
125
    DEBUGF("Reading partition tables...");
126
    disk_init();
127
    DEBUGF("Mounting partitions...");
128
    disk_mount_all();
129
    DEBUGF("Storage init finished.");
436 theseven 130
    wakeup_signal(&(ib->storagewakeup));
249 theseven 131
}
132
#endif
133
 
66 theseven 134
void initthread() INITCODE_ATTR;
135
void initthread()
2 theseven 136
{
126 theseven 137
#ifdef HAVE_I2C
15 theseven 138
    i2c_init();
126 theseven 139
#endif
54 theseven 140
    power_init();
249 theseven 141
    cputs(CONSOLE_BOOT, welcomestring);
142
#ifdef HAVE_STORAGE
436 theseven 143
    wakeup_init(&(ib->storagewakeup));
144
    thread_create(&(ib->storagethread), storagethreadname, storageinitthread,
145
                  ib->storagestack, sizeof(ib->storagestack), USER_THREAD, 127, true);
249 theseven 146
#endif
126 theseven 147
#ifdef HAVE_USB
15 theseven 148
    usb_init();
126 theseven 149
#endif
190 theseven 150
#ifdef HAVE_BACKLIGHT
151
    backlight_init();
152
#endif
130 theseven 153
#ifdef HAVE_BUTTON
154
    button_init();
155
#endif
126 theseven 156
#ifdef HAVE_TARGETINIT_LATE
157
    targetinit_late();
158
#endif
249 theseven 159
#ifdef HAVE_STORAGE
160
    while (true)
161
    {
436 theseven 162
        if (wakeup_wait(&(ib->storagewakeup), 100000) == THREAD_OK) break;
163
        enum thread_state state = thread_get_state(&(ib->storagethread));
164
        if (state == THREAD_DEFUNCT_ACK)
249 theseven 165
        {
436 theseven 166
            if (wakeup_wait(&(ib->storagewakeup), 0) == THREAD_OK) break;
167
            thread_terminate(&(ib->storagethread));
249 theseven 168
            break;
169
        }
170
    }
171
#endif
172
#ifdef HAVE_TARGETINIT_VERYLATE
173
    targetinit_verylate();
174
#endif
66 theseven 175
    DEBUGF("Finished initialisation sequence");
436 theseven 176
 
177
    struct bootoption* option;
178
    bool done = false;
179
    for (option = bootinfo.options; !done && option; option = option->next)
180
        switch (option->type)
181
        {
182
        case BOOTTYPE_PIGGYBACKED:
453 theseven 183
            done = execimage(option->source, true) != NULL;
436 theseven 184
            break;
185
 
186
#ifdef HAVE_BOOTFLASH
187
        case BOOTTYPE_BOOTFLASH:
188
        {
189
            int size = bootflash_filesize(option->source);
190
            if (size <= 0) break;
191
            void* buffer = memalign(0x10, size);
192
            if (!buffer) break;
193
            if (bootflash_read(option->source, buffer, 0, size) != size)
194
            {
195
                free(buffer);
196
                break;
197
            }
453 theseven 198
            done = execimage(buffer, false) != NULL;
436 theseven 199
            if (!done) free(buffer);
200
            break;
201
        }
202
#endif
203
 
204
#ifdef HAVE_STORAGE
205
        case BOOTTYPE_FILESYSTEM:
206
        {
207
            int fd = file_open(option->source, O_RDONLY);
208
            if (fd <= 0) break;
209
            int size = filesize(fd);
210
            if (size <= 0)
211
            {
212
                close(fd);
213
                break;
214
            }
215
            void* buffer = memalign(0x10, size);
216
            if (!buffer)
217
            {
218
                close(fd);
219
                break;
220
            }
221
            if (read(fd, buffer, size) != size)
222
            {
223
                free(buffer);
224
                close(fd);
225
                break;
226
            }
227
            close(fd);
453 theseven 228
            done = execimage(buffer, false) != NULL;
436 theseven 229
            if (!done) free(buffer);
230
            break;
231
        }
232
#endif
233
 
234
        default:
235
            cprintf(CONSOLE_BOOT, unknownboottypestr, option->type);
236
        }
237
    cputs(CONSOLE_BOOT, nobootoptionsstr);
437 theseven 238
    free(ib->bootalloc);
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
436 theseven 256
    malloc_init();
257
    size_t size = (size_t)(&bootinfo) - (size_t)(&_poolstart) + bootinfo.totalsize;
258
    void* bootalloc = malloc(size);
259
    size -= (size_t)(bootalloc) - (size_t)(&_poolstart);
260
    realloc(bootalloc, size);
261
    ib = (struct initbss*)malloc(sizeof(struct initbss));
262
    reownalloc(ib, &(ib->initthread));
263
    reownalloc(bootalloc, &(ib->initthread));
437 theseven 264
    ib->bootalloc = bootalloc;
436 theseven 265
    thread_create(&(ib->initthread), initthreadname, initthread, ib->initstack,
266
                  sizeof(ib->initstack), USER_THREAD, 127, true);
437 theseven 267
    interrupt_init();
66 theseven 268
}