Subversion Repositories freemyipod

Rev

Rev 963 | Details | Compare with Previous | 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
 
963 theseven 57
#ifndef BATTERY_BOOT_LOCKOUT_THRESHOLD
58
#define BATTERY_BOOT_LOCKOUT_THRESHOLD 0
59
#endif
60
 
61
 
436 theseven 62
extern int _poolstart;   // Not an int at all, but gcc complains about void types being
63
                         // used here, and we only need the address, so just make it happy...
64
 
65
 
66
enum boottype
89 theseven 67
{
436 theseven 68
    BOOTTYPE_PIGGYBACKED = 1,
69
    BOOTTYPE_BOOTFLASH = 2,
456 theseven 70
    BOOTTYPE_FILESYSTEM = 3,
71
    BOOTTYPE_FAKESUCCESS = 4
436 theseven 72
};
73
 
74
struct bootoption
75
{
456 theseven 76
    struct bootoption* success_next;
77
    struct bootoption* fail_next;
512 theseven 78
    int type;
436 theseven 79
    char* source;
80
};
81
 
82
struct bootinfo
83
{
89 theseven 84
    char signature[8];
85
    int version;
436 theseven 86
    void* baseaddr;
87
    size_t totalsize;
88
    struct bootoption* options;
89 theseven 89
};
90
 
91
 
436 theseven 92
struct initbss
93
{
94
    struct scheduler_thread initthread;
95
    uint32_t initstack[0x400];
96
#ifdef HAVE_STORAGE
97
    struct scheduler_thread storagethread;
98
    uint32_t storagestack[0x400];
99
    struct wakeup storagewakeup;
100
#endif
101
};
102
 
103
 
427 farthen 104
static const char welcomestring[] INITCONST_ATTR = "emCORE v" VERSION " r" VERSION_SVN "\n\n";
110 theseven 105
static const char initthreadname[] INITCONST_ATTR = "Initialization thread";
436 theseven 106
static const char unknownboottypestr[] INITCONST_ATTR = "Skipping boot option with unknown type %d\n";
107
static const char nobootoptionsstr[] INITCONST_ATTR = "No usable boot options, waiting for USB commands\n\n";
249 theseven 108
#ifdef HAVE_STORAGE
436 theseven 109
static const char storagethreadname[] INITCONST_ATTR = "Storage init thread";
249 theseven 110
#endif
436 theseven 111
 
112
struct bootinfo bootinfo INITTAIL_ATTR =
89 theseven 113
{
429 theseven 114
    .signature = "emCOboot",
436 theseven 115
    .version = 1,
116
    .baseaddr = &bootinfo,
117
    .totalsize = sizeof(struct bootinfo),
118
    .options = NULL
89 theseven 119
};
15 theseven 120
 
87 theseven 121
 
89 theseven 122
#ifdef HAVE_STORAGE
835 theseven 123
void storageinitthread(void* arg0, void* arg1, void* arg2, void* arg3) INITCODE_ATTR;
124
void storageinitthread(void* arg0, void* arg1, void* arg2, void* arg3)
249 theseven 125
{
835 theseven 126
    struct initbss* ib = (struct initbss*)arg0;
963 theseven 127
    DEBUGF("Battery state: %d, %d mV, %d mAh", read_battery_state(0),
128
           read_battery_voltage(0), read_battery_mwh_current(0));
129
    switch (read_battery_state(0))
936 theseven 130
    {
963 theseven 131
    case BATTERY_STATE_NONPRESENT:
132
        cputs(CONSOLE_BOOT, "No battery connected.\n");
133
        break;
134
    case BATTERY_STATE_IDLE:
135
    case BATTERY_STATE_CHARGING:
136
    case BATTERY_STATE_DISCHARGING:
137
        if (read_battery_mwh_current(0) <= BATTERY_BOOT_LOCKOUT_THRESHOLD)
936 theseven 138
        {
963 theseven 139
            backlight_set_brightness(50);
140
            cputs(CONSOLE_BOOT, "The battery is discharged.\n"
141
                                "Please connect to a power supply\n"
142
                                "and wait a few minutes.\n");
143
            while (read_battery_mwh_current(0) <= BATTERY_BOOT_LOCKOUT_THRESHOLD)
936 theseven 144
            {
963 theseven 145
                DEBUGF("Battery state: %d, %d mV, %d mAh", read_battery_state(0),
146
                       read_battery_voltage(0), read_battery_mwh_current(0));
147
                sleep(10000000);
148
                if (read_battery_state(0) != BATTERY_STATE_CHARGING)
149
                {
150
                    shutdown(true);
151
                    power_off();
152
                }
936 theseven 153
            }
963 theseven 154
            backlight_set_brightness(100);
936 theseven 155
        }
156
    }
249 theseven 157
    DEBUGF("Initializing storage drivers...");
921 theseven 158
    int rc = storage_init();
159
    if (IS_ERR(rc))
160
    {
161
        DEBUGF("Storage init error: %08X\n", rc);
162
        cprintf(CONSOLE_BOOT, "Storage init error: %08X\n", rc);
163
    }
249 theseven 164
    DEBUGF("Initializing storage subsystem...");
165
    disk_init_subsystem();
166
    DEBUGF("Mounting partitions...");
963 theseven 167
    rc = disk_mount_all();
168
    if (IS_ERR(rc))
169
    {
170
        DEBUGF("FS mount error: %08X\n", rc);
171
        cprintf(CONSOLE_BOOT, "FS mount error: %08X\n", rc);
172
    }
249 theseven 173
    DEBUGF("Storage init finished.");
436 theseven 174
    wakeup_signal(&(ib->storagewakeup));
249 theseven 175
}
176
#endif
177
 
835 theseven 178
void initthread(void* arg0, void* arg1, void* arg2, void* arg3) INITCODE_ATTR;
842 theseven 179
void initthread(void* arg0, void* arg1, void* arg2, void* arg3)
2 theseven 180
{
835 theseven 181
    struct initbss* ib = (struct initbss*)arg0;
126 theseven 182
#ifdef HAVE_I2C
15 theseven 183
    i2c_init();
126 theseven 184
#endif
54 theseven 185
    power_init();
249 theseven 186
    cputs(CONSOLE_BOOT, welcomestring);
187
#ifdef HAVE_STORAGE
436 theseven 188
    wakeup_init(&(ib->storagewakeup));
835 theseven 189
    thread_create(&(ib->storagethread), storagethreadname, storageinitthread, ib->storagestack,
190
                  sizeof(ib->storagestack), USER_THREAD, 127, true, ib, NULL, NULL, NULL);
249 theseven 191
#endif
126 theseven 192
#ifdef HAVE_USB
891 theseven 193
    usbmanager_init();
126 theseven 194
#endif
190 theseven 195
#ifdef HAVE_BACKLIGHT
196
    backlight_init();
197
#endif
130 theseven 198
#ifdef HAVE_BUTTON
199
    button_init();
200
#endif
126 theseven 201
#ifdef HAVE_TARGETINIT_LATE
202
    targetinit_late();
203
#endif
249 theseven 204
#ifdef HAVE_STORAGE
205
    while (true)
206
    {
436 theseven 207
        if (wakeup_wait(&(ib->storagewakeup), 100000) == THREAD_OK) break;
208
        enum thread_state state = thread_get_state(&(ib->storagethread));
209
        if (state == THREAD_DEFUNCT_ACK)
249 theseven 210
        {
436 theseven 211
            if (wakeup_wait(&(ib->storagewakeup), 0) == THREAD_OK) break;
212
            thread_terminate(&(ib->storagethread));
249 theseven 213
            break;
214
        }
215
    }
216
#endif
217
#ifdef HAVE_TARGETINIT_VERYLATE
218
    targetinit_verylate();
219
#endif
66 theseven 220
    DEBUGF("Finished initialisation sequence");
436 theseven 221
 
456 theseven 222
    struct bootoption* option = bootinfo.options;
223
    bool success = false;
224
    while (option)
225
    {
226
        success = false;
436 theseven 227
        switch (option->type)
228
        {
229
        case BOOTTYPE_PIGGYBACKED:
835 theseven 230
            success = execimage(option->source, true, 0, NULL) != NULL;
436 theseven 231
            break;
232
 
233
#ifdef HAVE_BOOTFLASH
234
        case BOOTTYPE_BOOTFLASH:
235
        {
236
            int size = bootflash_filesize(option->source);
237
            if (size <= 0) break;
238
            void* buffer = memalign(0x10, size);
239
            if (!buffer) break;
240
            if (bootflash_read(option->source, buffer, 0, size) != size)
241
            {
242
                free(buffer);
243
                break;
244
            }
835 theseven 245
            success = execimage(buffer, false, 0, NULL) != NULL;
436 theseven 246
            break;
247
        }
248
#endif
249
 
250
#ifdef HAVE_STORAGE
251
        case BOOTTYPE_FILESYSTEM:
252
        {
253
            int fd = file_open(option->source, O_RDONLY);
254
            if (fd <= 0) break;
255
            int size = filesize(fd);
256
            if (size <= 0)
257
            {
258
                close(fd);
259
                break;
260
            }
261
            void* buffer = memalign(0x10, size);
262
            if (!buffer)
263
            {
264
                close(fd);
265
                break;
266
            }
267
            if (read(fd, buffer, size) != size)
268
            {
269
                free(buffer);
270
                close(fd);
271
                break;
272
            }
273
            close(fd);
835 theseven 274
            success = execimage(buffer, false, 0, NULL) != NULL;
436 theseven 275
            break;
276
        }
277
#endif
278
 
456 theseven 279
        case BOOTTYPE_FAKESUCCESS:
280
            success = true;
281
            break;
282
 
436 theseven 283
        default:
284
            cprintf(CONSOLE_BOOT, unknownboottypestr, option->type);
285
        }
456 theseven 286
        if (success) option = option->success_next;
287
        else option = option->fail_next;
288
    }
289
    if (!success) cputs(CONSOLE_BOOT, nobootoptionsstr);
66 theseven 290
}
291
 
292
void init() INITCODE_ATTR;
293
void init()
294
{
126 theseven 295
#ifdef HAVE_TARGETINIT_VERYEARLY
296
    targetinit_veryearly();
297
#endif
66 theseven 298
    scheduler_init();
299
    console_init();
126 theseven 300
#ifdef HAVE_LCD
66 theseven 301
    lcd_init();
302
    lcdconsole_init();
126 theseven 303
#endif
304
#ifdef HAVE_TARGETINIT_EARLY
305
    targetinit_early();
306
#endif
436 theseven 307
    malloc_init();
308
    size_t size = (size_t)(&bootinfo) - (size_t)(&_poolstart) + bootinfo.totalsize;
309
    void* bootalloc = malloc(size);
310
    size -= (size_t)(bootalloc) - (size_t)(&_poolstart);
311
    realloc(bootalloc, size);
835 theseven 312
    struct initbss* ib = (struct initbss*)malloc(sizeof(struct initbss));
814 theseven 313
    reownalloc(ib, OWNER_TYPE(OWNER_THREAD, &(ib->initthread)));
314
    reownalloc(bootalloc, OWNER_TYPE(OWNER_THREAD, &(ib->initthread)));
436 theseven 315
    thread_create(&(ib->initthread), initthreadname, initthread, ib->initstack,
842 theseven 316
                  sizeof(ib->initstack), OS_THREAD, 127, true, ib, NULL, NULL, NULL);
597 theseven 317
    timer_init();
437 theseven 318
    interrupt_init();
66 theseven 319
}