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
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS is free software: you can redistribute it and/or
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
//
13
//    emBIOS is distributed in the hope that it will be useful,
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
19
//    with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
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
2 theseven 51
 
87 theseven 52
 
89 theseven 53
struct bootinfo_t
54
{
55
    char signature[8];
56
    int version;
57
    bool trydataflash;
58
    char dataflashpath[256];
59
    bool dataflashflags;
140 theseven 60
    void* dataflashdest;
89 theseven 61
    bool trybootflash;
62
    char bootimagename[8];
63
    bool bootflashflags;
140 theseven 64
    void* bootflashdest;
89 theseven 65
    bool trymemmapped;
66
    void* memmappedaddr;
95 theseven 67
    int memmappedsize;
89 theseven 68
    bool memmappedflags;
140 theseven 69
    void* memmappeddest;
89 theseven 70
};
71
 
72
 
32 theseven 73
static const char welcomestring[] INITCONST_ATTR = "emBIOS v" VERSION " r" VERSION_SVN "\n\n";
110 theseven 74
static const char initthreadname[] INITCONST_ATTR = "Initialization thread";
89 theseven 75
static uint32_t initstack[0x400] INITSTACK_ATTR;
76
extern int _loadspaceend;
98 theseven 77
struct bootinfo_t bootinfo_src INITHEAD_ATTR =
89 theseven 78
{
79
    .signature = "emBIboot",
80
    .version = 0,
81
    .trydataflash = false,
82
    .trybootflash = false,
83
    .trymemmapped = false
84
};
15 theseven 85
 
87 theseven 86
 
89 theseven 87
void boot()
88
{
89
    struct bootinfo_t bootinfo = bootinfo_src;
90
#ifdef HAVE_STORAGE
91
    if (bootinfo.trydataflash)
92
    {
93
        int fd = file_open(bootinfo.dataflashpath, O_RDONLY);
94
        if (fd < 0) goto dataflashfailed;
95 theseven 95
        int size = filesize(fd);
96
        if (size < 0) goto dataflashfailed;
89 theseven 97
        if (bootinfo.dataflashflags & 1)
98
        {
99
            void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1));
100
            if (read(fd, addr, size) != size) goto dataflashfailed;
140 theseven 101
            if (ucl_decompress(addr, size, bootinfo.dataflashdest, (uint32_t*)&size))
102
                goto dataflashfailed;
89 theseven 103
        }
140 theseven 104
        else if (read(fd, bootinfo.dataflashdest, size) != size) goto dataflashfailed;
105
        if (execimage(bootinfo.dataflashdest) >= 0) return;
89 theseven 106
    }
107
dataflashfailed:
108
#endif
109
#ifdef HAVE_BOOTFLASH
110
    if (bootinfo.trybootflash)
111
    {
95 theseven 112
        int size = bootflash_filesize(bootinfo.bootimagename);
89 theseven 113
        if (size < 0) goto bootflashfailed;
114
#ifdef BOOTFLASH_IS_MEMMAPPED
115
        void* addr = bootflash_getaddr(bootinfo.bootimagename);
95 theseven 116
        if (!addr) goto bootflashfailed;
89 theseven 117
        if (bootinfo.bootflashflags & 1)
118
        {
140 theseven 119
            if (ucl_decompress(addr, size, bootinfo.bootflashdest, (uint32_t*)&size))
120
                goto bootflashfailed;
121
            if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 122
        }
123
        else if (bootinfo.bootflashflags & 2)
124
        {
140 theseven 125
            memcpy(bootinfo.bootflashdest, addr, size);
126
            if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 127
        }
133 theseven 128
        else if (execimage(addr) >= 0) return;
89 theseven 129
#else
130
        if (bootinfo.bootflashflags & 1)
131
        {
132
            void* addr = (void*)((((uint32_t)&_loadspaceend) - size) & ~(CACHEALIGN_SIZE - 1));
95 theseven 133
            if (bootflash_read(bootinfo.bootimagename, addr, 0, size) != size)
134
                goto bootflashfailed;
140 theseven 135
            if (ucl_decompress(addr, size, bootinfo.bootflashdest, (uint32_t*)&size))
136
                goto bootflashfailed;
89 theseven 137
        }
140 theseven 138
        else if (bootflash_read(bootinfo.bootimagename, bootinfo.bootflashdest, 0, size) != size)
95 theseven 139
            goto bootflashfailed;
140 theseven 140
        if (execimage(bootinfo.bootflashdest) >= 0) return;
89 theseven 141
#endif
142
    }
143
bootflashfailed:
144
#endif
145
    if (bootinfo.trymemmapped)
146
    {
95 theseven 147
        int size = bootinfo.memmappedsize;
133 theseven 148
        if (bootinfo.memmappedflags & 1)
89 theseven 149
        {
140 theseven 150
            if (ucl_decompress(bootinfo.memmappedaddr, size,
151
                               bootinfo.memmappeddest, (uint32_t*)&size))
89 theseven 152
                goto memmappedfailed;
140 theseven 153
            if (execimage(bootinfo.memmappeddest) >= 0) return;
89 theseven 154
        }
133 theseven 155
        else if (bootinfo.memmappedflags & 2)
89 theseven 156
        {
140 theseven 157
            memcpy(bootinfo.memmappeddest, bootinfo.memmappedaddr, size);
158
            if (execimage(bootinfo.memmappeddest) >= 0) return;
89 theseven 159
        }
133 theseven 160
        else if (execimage(bootinfo.memmappedaddr) >= 0) return;
89 theseven 161
    }
162
memmappedfailed:
163
    if (bootinfo.trydataflash || bootinfo.trybootflash || bootinfo.trymemmapped)
164
        cputs(CONSOLE_BOOT, "Could not find a usable boot image!\n");
165
    cputs(CONSOLE_BOOT, "Waiting for USB commands\n\n");
166
}
167
 
66 theseven 168
void initthread() INITCODE_ATTR;
169
void initthread()
2 theseven 170
{
126 theseven 171
#ifdef HAVE_I2C
15 theseven 172
    i2c_init();
126 theseven 173
#endif
54 theseven 174
    power_init();
126 theseven 175
#ifdef HAVE_USB
15 theseven 176
    usb_init();
126 theseven 177
#endif
138 theseven 178
    cputs(CONSOLE_BOOT, welcomestring);
130 theseven 179
#ifdef HAVE_BUTTON
180
    button_init();
181
#endif
126 theseven 182
#ifdef HAVE_STORAGE
66 theseven 183
    DEBUGF("Initializing storage drivers...");
58 theseven 184
    storage_init();
66 theseven 185
    DEBUGF("Initializing storage subsystem...");
58 theseven 186
    disk_init_subsystem();
66 theseven 187
    DEBUGF("Reading partition tables...");
58 theseven 188
    disk_init();
66 theseven 189
    DEBUGF("Mounting partitions...");
58 theseven 190
    disk_mount_all();
126 theseven 191
#endif
192
#ifdef HAVE_TARGETINIT_LATE
193
    targetinit_late();
194
#endif
66 theseven 195
    DEBUGF("Finished initialisation sequence");
89 theseven 196
    boot();
66 theseven 197
}
198
 
199
void init() INITCODE_ATTR;
200
void init()
201
{
126 theseven 202
#ifdef HAVE_TARGETINIT_VERYEARLY
203
    targetinit_veryearly();
204
#endif
66 theseven 205
    scheduler_init();
206
    console_init();
126 theseven 207
#ifdef HAVE_LCD
66 theseven 208
    lcd_init();
209
    lcdconsole_init();
126 theseven 210
#endif
211
#ifdef HAVE_TARGETINIT_EARLY
212
    targetinit_early();
213
#endif
66 theseven 214
    interrupt_init();
215
    thread_create(initthreadname, initthread, initstack,
216
                  sizeof(initstack), USER_THREAD, 127, true);
217
}