Subversion Repositories freemyipod

Rev

Rev 842 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
90 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
427 farthen 6
//    This file is part of emCORE.
90 theseven 7
//
427 farthen 8
//    emCORE is free software: you can redistribute it and/or
90 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,
90 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/>.
90 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "console.h"
26
#include "execimage.h"
92 theseven 27
#include "mmu.h"
465 theseven 28
#include "malloc.h"
90 theseven 29
 
30
 
842 theseven 31
struct scheduler_thread* execimage(void* image, bool copy, int argc, const char* const* argv)
90 theseven 32
{
835 theseven 33
    int i;
453 theseven 34
    struct emcoreapp_header* header = (struct emcoreapp_header*)image;
35
    if (memcmp(header, "emCOexec", 8))
90 theseven 36
    {
453 theseven 37
        cprintf(CONSOLE_BOOT, "execimage: Bad signature: "
90 theseven 38
                              "%02X %02X %02X %02X %02X %02X %02X %02X\n",
39
                header->signature[0], header->signature[1], header->signature[2],
40
                header->signature[3], header->signature[4], header->signature[5],
41
                header->signature[6], header->signature[7]);
465 theseven 42
        if (!copy) free(image);
453 theseven 43
        return NULL;
90 theseven 44
    }
453 theseven 45
    if (header->version != EMCOREAPP_HEADER_VERSION)
90 theseven 46
    {
47
        cprintf(CONSOLE_BOOT, "execimage: Unsupported version! (%08X)\n", header->version);
465 theseven 48
        if (!copy) free(image);
453 theseven 49
        return NULL;
90 theseven 50
    }
453 theseven 51
    off_t offset = header->textstart;
52
    size_t textsize = header->textsize;
53
    size_t bsssize = header->bsssize;
54
    size_t stacksize = header->stacksize;
55
	off_t entrypoint = header->entrypoint;
56
	off_t relocstart = header->relocstart - offset;
57
	uint32_t reloccount = header->reloccount;
58
	bool compressed = header->flags & EMCOREAPP_FLAG_COMPRESSED;
465 theseven 59
	bool lib = header->flags & EMCOREAPP_FLAG_LIBRARY;
835 theseven 60
    uint32_t argsize = 0;
61
    if (argv)
62
        for (i = 0; i < argc; i++)
63
            argsize += 5 + strlen(argv[i]);
64
    else argc = 0;
842 theseven 65
    argsize = (argsize + 3) & ~3;
465 theseven 66
    size_t finalsize;
67
    if (lib) finalsize = textsize + bsssize;
835 theseven 68
    else finalsize = textsize + bsssize + argsize + stacksize;
453 theseven 69
    size_t datasize = relocstart + reloccount * 4;
70
    size_t tempsize = MAX(finalsize, datasize);
71
    if (compressed)
90 theseven 72
    {
626 theseven 73
        void* alloc = memalign(CACHEALIGN_SIZE, tempsize);
453 theseven 74
        if (!alloc)
75
        {
76
            cprintf(CONSOLE_BOOT, "execimage: Out of memory!\n");
465 theseven 77
            if (!copy) free(image);
453 theseven 78
            return NULL;
79
        }
80
        uint32_t decompsize;
466 theseven 81
        ucl_decompress(image + offset, datasize, alloc, &decompsize);
465 theseven 82
        if (!copy) free(image);
453 theseven 83
        if (datasize != decompsize)
84
        {
466 theseven 85
            cprintf(CONSOLE_BOOT, "execimage: Decompression failed!\n");
453 theseven 86
            free(alloc);
87
            return NULL;
88
        }
89
        image = alloc;
90 theseven 90
    }
626 theseven 91
    else if (copy || (((uint32_t)image) & (CACHEALIGN_SIZE - 1)))
453 theseven 92
    {
626 theseven 93
        void* alloc = memalign(CACHEALIGN_SIZE, tempsize);
453 theseven 94
        if (!alloc)
95
        {
96
            cprintf(CONSOLE_BOOT, "execimage: Out of memory!\n");
626 theseven 97
            if (!copy) free(image);
453 theseven 98
            return NULL;
99
        }
100
        memcpy(alloc, image + offset, datasize);
626 theseven 101
        if (!copy) free(image);
453 theseven 102
        image = alloc;
103
    }
104
    else
105
    {
106
        memcpy(image, image + offset, datasize);
626 theseven 107
        void* newimage = realign(image, CACHEALIGN_SIZE, tempsize);
465 theseven 108
        if (!newimage)
453 theseven 109
        {
465 theseven 110
            free(image);
453 theseven 111
            cprintf(CONSOLE_BOOT, "execimage: Out of memory!\n");
112
            return NULL;
113
        }
465 theseven 114
        else image = newimage;
453 theseven 115
    }
116
    for (; reloccount; reloccount--, relocstart += 4)
117
    {
118
        off_t reloc = *((off_t*)(image + relocstart));
119
        uint32_t data = *((uint32_t*)(image + reloc));
120
        *((void**)(image + reloc)) = image + data;
121
    }
122
    if (tempsize != finalsize) realloc(image, finalsize); /* Can only shrink => safe */
835 theseven 123
    void* ptr = image + textsize;
124
    memset(ptr, 0, bsssize);
125
    ptr += bsssize;
842 theseven 126
    void* argv_copy = ptr;
835 theseven 127
    if (argv)
128
    {
129
        memcpy(image + textsize + bsssize, argv, argc * 4);
130
        ptr += argc * 4;
131
        for (i = 0; i < argc; i++)
132
        {
133
            uint32_t len = strlen(argv[i]);
134
            memcpy(ptr, argv[i], len);
135
            ptr += len;
136
        }
137
    }
842 theseven 138
    ptr = (void*)(((int)ptr + 3) & ~3);
92 theseven 139
    clean_dcache();
140
    invalidate_icache();
465 theseven 141
    struct scheduler_thread* thread;
835 theseven 142
    if (lib)
143
        thread = (struct scheduler_thread*)library_register(image, image + entrypoint, argc, argv);
465 theseven 144
    else
145
    {
835 theseven 146
        thread = thread_create(NULL, NULL, image + entrypoint, ptr, stacksize,
842 theseven 147
                               USER_THREAD, 127, false, (void*)argc, argv_copy, NULL, NULL);
465 theseven 148
        if (thread)
149
        {
814 theseven 150
            reownalloc(image, OWNER_TYPE(OWNER_THREAD, thread));
465 theseven 151
            thread_resume(thread);
152
        }
153
        else free(image);
154
    }
453 theseven 155
    return thread;
90 theseven 156
}