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
891 theseven 42
#include "usb/usbglue.h"
85 theseven 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,
456 theseven 65
    BOOTTYPE_FILESYSTEM = 3,
66
    BOOTTYPE_FAKESUCCESS = 4
436 theseven 67
};
68
 
69
struct bootoption
70
{
456 theseven 71
    struct bootoption* success_next;
72
    struct bootoption* fail_next;
512 theseven 73
    int type;
436 theseven 74
    char* source;
75
};
76
 
77
struct bootinfo
78
{
89 theseven 79
    char signature[8];
80
    int version;
436 theseven 81
    void* baseaddr;
82
    size_t totalsize;
83
    struct bootoption* options;
89 theseven 84
};
85
 
86
 
436 theseven 87
struct initbss
88
{
89
    struct scheduler_thread initthread;
90
    uint32_t initstack[0x400];
91
#ifdef HAVE_STORAGE
92
    struct scheduler_thread storagethread;
93
    uint32_t storagestack[0x400];
94
    struct wakeup storagewakeup;
95
#endif
96
};
97
 
98
 
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
835 theseven 118
void storageinitthread(void* arg0, void* arg1, void* arg2, void* arg3) INITCODE_ATTR;
119
void storageinitthread(void* arg0, void* arg1, void* arg2, void* arg3)
249 theseven 120
{
835 theseven 121
    struct initbss* ib = (struct initbss*)arg0;
936 theseven 122
    int threshold = 0;
123
    DEBUGF("Battery state: %d mV, %d mAh", read_battery_voltage(0), read_battery_mwh_current(0));
124
    if (read_battery_mwh_current(0) <= threshold)
125
    {
126
        backlight_set_brightness(50);
127
        cputs(CONSOLE_BOOT, "The battery is discharged.\n"
128
                            "Please connect to a power supply\n"
129
                            "and wait a few minutes.\n");
130
        while (read_battery_mwh_current(0) <= threshold)
131
        {
132
            DEBUGF("Battery state: %d mV, %d mAh", read_battery_voltage(0), read_battery_mwh_current(0));
133
            sleep(10000000);
134
            if (read_input_state(0) != INPUT_STATE_ACTIVE)
135
            {
136
                shutdown(true);
137
                power_off();
138
            }
139
        }
140
        backlight_set_brightness(100);
141
    }
249 theseven 142
    DEBUGF("Initializing storage drivers...");
921 theseven 143
    int rc = storage_init();
144
    if (IS_ERR(rc))
145
    {
146
        DEBUGF("Storage init error: %08X\n", rc);
147
        cprintf(CONSOLE_BOOT, "Storage init error: %08X\n", rc);
148
    }
249 theseven 149
    DEBUGF("Initializing storage subsystem...");
150
    disk_init_subsystem();
151
    DEBUGF("Reading partition tables...");
152
    disk_init();
153
    DEBUGF("Mounting partitions...");
154
    disk_mount_all();
155
    DEBUGF("Storage init finished.");
436 theseven 156
    wakeup_signal(&(ib->storagewakeup));
249 theseven 157
}
158
#endif
159
 
835 theseven 160
void initthread(void* arg0, void* arg1, void* arg2, void* arg3) INITCODE_ATTR;
842 theseven 161
void initthread(void* arg0, void* arg1, void* arg2, void* arg3)
2 theseven 162
{
835 theseven 163
    struct initbss* ib = (struct initbss*)arg0;
126 theseven 164
#ifdef HAVE_I2C
15 theseven 165
    i2c_init();
126 theseven 166
#endif
54 theseven 167
    power_init();
249 theseven 168
    cputs(CONSOLE_BOOT, welcomestring);
169
#ifdef HAVE_STORAGE
436 theseven 170
    wakeup_init(&(ib->storagewakeup));
835 theseven 171
    thread_create(&(ib->storagethread), storagethreadname, storageinitthread, ib->storagestack,
172
                  sizeof(ib->storagestack), USER_THREAD, 127, true, ib, NULL, NULL, NULL);
249 theseven 173
#endif
126 theseven 174
#ifdef HAVE_USB
891 theseven 175
    usbmanager_init();
126 theseven 176
#endif
190 theseven 177
#ifdef HAVE_BACKLIGHT
178
    backlight_init();
179
#endif
130 theseven 180
#ifdef HAVE_BUTTON
181
    button_init();
182
#endif
126 theseven 183
#ifdef HAVE_TARGETINIT_LATE
184
    targetinit_late();
185
#endif
249 theseven 186
#ifdef HAVE_STORAGE
187
    while (true)
188
    {
436 theseven 189
        if (wakeup_wait(&(ib->storagewakeup), 100000) == THREAD_OK) break;
190
        enum thread_state state = thread_get_state(&(ib->storagethread));
191
        if (state == THREAD_DEFUNCT_ACK)
249 theseven 192
        {
436 theseven 193
            if (wakeup_wait(&(ib->storagewakeup), 0) == THREAD_OK) break;
194
            thread_terminate(&(ib->storagethread));
249 theseven 195
            break;
196
        }
197
    }
198
#endif
199
#ifdef HAVE_TARGETINIT_VERYLATE
200
    targetinit_verylate();
201
#endif
66 theseven 202
    DEBUGF("Finished initialisation sequence");
436 theseven 203
 
456 theseven 204
    struct bootoption* option = bootinfo.options;
205
    bool success = false;
206
    while (option)
207
    {
208
        success = false;
436 theseven 209
        switch (option->type)
210
        {
211
        case BOOTTYPE_PIGGYBACKED:
835 theseven 212
            success = execimage(option->source, true, 0, NULL) != NULL;
436 theseven 213
            break;
214
 
215
#ifdef HAVE_BOOTFLASH
216
        case BOOTTYPE_BOOTFLASH:
217
        {
218
            int size = bootflash_filesize(option->source);
219
            if (size <= 0) break;
220
            void* buffer = memalign(0x10, size);
221
            if (!buffer) break;
222
            if (bootflash_read(option->source, buffer, 0, size) != size)
223
            {
224
                free(buffer);
225
                break;
226
            }
835 theseven 227
            success = execimage(buffer, false, 0, NULL) != NULL;
436 theseven 228
            break;
229
        }
230
#endif
231
 
232
#ifdef HAVE_STORAGE
233
        case BOOTTYPE_FILESYSTEM:
234
        {
235
            int fd = file_open(option->source, O_RDONLY);
236
            if (fd <= 0) break;
237
            int size = filesize(fd);
238
            if (size <= 0)
239
            {
240
                close(fd);
241
                break;
242
            }
243
            void* buffer = memalign(0x10, size);
244
            if (!buffer)
245
            {
246
                close(fd);
247
                break;
248
            }
249
            if (read(fd, buffer, size) != size)
250
            {
251
                free(buffer);
252
                close(fd);
253
                break;
254
            }
255
            close(fd);
835 theseven 256
            success = execimage(buffer, false, 0, NULL) != NULL;
436 theseven 257
            break;
258
        }
259
#endif
260
 
456 theseven 261
        case BOOTTYPE_FAKESUCCESS:
262
            success = true;
263
            break;
264
 
436 theseven 265
        default:
266
            cprintf(CONSOLE_BOOT, unknownboottypestr, option->type);
267
        }
456 theseven 268
        if (success) option = option->success_next;
269
        else option = option->fail_next;
270
    }
271
    if (!success) cputs(CONSOLE_BOOT, nobootoptionsstr);
66 theseven 272
}
273
 
274
void init() INITCODE_ATTR;
275
void init()
276
{
126 theseven 277
#ifdef HAVE_TARGETINIT_VERYEARLY
278
    targetinit_veryearly();
279
#endif
66 theseven 280
    scheduler_init();
281
    console_init();
126 theseven 282
#ifdef HAVE_LCD
66 theseven 283
    lcd_init();
284
    lcdconsole_init();
126 theseven 285
#endif
286
#ifdef HAVE_TARGETINIT_EARLY
287
    targetinit_early();
288
#endif
436 theseven 289
    malloc_init();
290
    size_t size = (size_t)(&bootinfo) - (size_t)(&_poolstart) + bootinfo.totalsize;
291
    void* bootalloc = malloc(size);
292
    size -= (size_t)(bootalloc) - (size_t)(&_poolstart);
293
    realloc(bootalloc, size);
835 theseven 294
    struct initbss* ib = (struct initbss*)malloc(sizeof(struct initbss));
814 theseven 295
    reownalloc(ib, OWNER_TYPE(OWNER_THREAD, &(ib->initthread)));
296
    reownalloc(bootalloc, OWNER_TYPE(OWNER_THREAD, &(ib->initthread)));
436 theseven 297
    thread_create(&(ib->initthread), initthreadname, initthread, ib->initstack,
842 theseven 298
                  sizeof(ib->initstack), OS_THREAD, 127, true, ib, NULL, NULL, NULL);
597 theseven 299
    timer_init();
437 theseven 300
    interrupt_init();
66 theseven 301
}