| 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"
|
| 90 |
theseven |
28 |
|
|
|
29 |
|
| 453 |
theseven |
30 |
struct scheduler_thread* execimage(void* image, bool copy)
|
| 90 |
theseven |
31 |
{
|
| 453 |
theseven |
32 |
struct emcoreapp_header* header = (struct emcoreapp_header*)image;
|
|
|
33 |
if (memcmp(header, "emCOexec", 8))
|
| 90 |
theseven |
34 |
{
|
| 453 |
theseven |
35 |
cprintf(CONSOLE_BOOT, "execimage: Bad signature: "
|
| 90 |
theseven |
36 |
"%02X %02X %02X %02X %02X %02X %02X %02X\n",
|
|
|
37 |
header->signature[0], header->signature[1], header->signature[2],
|
|
|
38 |
header->signature[3], header->signature[4], header->signature[5],
|
|
|
39 |
header->signature[6], header->signature[7]);
|
| 453 |
theseven |
40 |
return NULL;
|
| 90 |
theseven |
41 |
}
|
| 453 |
theseven |
42 |
if (header->version != EMCOREAPP_HEADER_VERSION)
|
| 90 |
theseven |
43 |
{
|
|
|
44 |
cprintf(CONSOLE_BOOT, "execimage: Unsupported version! (%08X)\n", header->version);
|
| 453 |
theseven |
45 |
return NULL;
|
| 90 |
theseven |
46 |
}
|
| 453 |
theseven |
47 |
off_t offset = header->textstart;
|
|
|
48 |
size_t textsize = header->textsize;
|
|
|
49 |
size_t bsssize = header->bsssize;
|
|
|
50 |
size_t stacksize = header->stacksize;
|
|
|
51 |
off_t entrypoint = header->entrypoint;
|
|
|
52 |
off_t relocstart = header->relocstart - offset;
|
|
|
53 |
uint32_t reloccount = header->reloccount;
|
|
|
54 |
bool compressed = header->flags & EMCOREAPP_FLAG_COMPRESSED;
|
|
|
55 |
size_t finalsize = textsize + bsssize + stacksize;
|
|
|
56 |
size_t datasize = relocstart + reloccount * 4;
|
|
|
57 |
size_t tempsize = MAX(finalsize, datasize);
|
|
|
58 |
if (compressed)
|
| 90 |
theseven |
59 |
{
|
| 453 |
theseven |
60 |
void* alloc = malloc(tempsize);
|
|
|
61 |
if (!alloc)
|
|
|
62 |
{
|
|
|
63 |
cprintf(CONSOLE_BOOT, "execimage: Out of memory!\n");
|
|
|
64 |
return NULL;
|
|
|
65 |
}
|
|
|
66 |
uint32_t decompsize;
|
|
|
67 |
if (ucl_decompress(image + offset, datasize, alloc, &decompsize))
|
|
|
68 |
{
|
|
|
69 |
cprintf(CONSOLE_BOOT, "execimage: Decompression failed!\n");
|
|
|
70 |
free(alloc);
|
|
|
71 |
return NULL;
|
|
|
72 |
}
|
|
|
73 |
if (datasize != decompsize)
|
|
|
74 |
{
|
|
|
75 |
cprintf(CONSOLE_BOOT, "execimage: Decompressed size mismatch!\n");
|
|
|
76 |
free(alloc);
|
|
|
77 |
return NULL;
|
|
|
78 |
}
|
|
|
79 |
if (!copy) free(image);
|
|
|
80 |
image = alloc;
|
| 90 |
theseven |
81 |
}
|
| 453 |
theseven |
82 |
else if (copy)
|
|
|
83 |
{
|
|
|
84 |
void* alloc = malloc(tempsize);
|
|
|
85 |
if (!alloc)
|
|
|
86 |
{
|
|
|
87 |
cprintf(CONSOLE_BOOT, "execimage: Out of memory!\n");
|
|
|
88 |
return NULL;
|
|
|
89 |
}
|
|
|
90 |
memcpy(alloc, image + offset, datasize);
|
|
|
91 |
image = alloc;
|
|
|
92 |
}
|
|
|
93 |
else
|
|
|
94 |
{
|
|
|
95 |
memcpy(image, image + offset, datasize);
|
|
|
96 |
image = realloc(image, tempsize);
|
|
|
97 |
if (!image)
|
|
|
98 |
{
|
|
|
99 |
cprintf(CONSOLE_BOOT, "execimage: Out of memory!\n");
|
|
|
100 |
return NULL;
|
|
|
101 |
}
|
|
|
102 |
}
|
|
|
103 |
for (; reloccount; reloccount--, relocstart += 4)
|
|
|
104 |
{
|
|
|
105 |
off_t reloc = *((off_t*)(image + relocstart));
|
|
|
106 |
uint32_t data = *((uint32_t*)(image + reloc));
|
|
|
107 |
*((void**)(image + reloc)) = image + data;
|
|
|
108 |
}
|
|
|
109 |
if (tempsize != finalsize) realloc(image, finalsize); /* Can only shrink => safe */
|
| 92 |
theseven |
110 |
clean_dcache();
|
|
|
111 |
invalidate_icache();
|
| 453 |
theseven |
112 |
struct scheduler_thread* thread = thread_create(NULL, NULL, image + entrypoint,
|
|
|
113 |
image + textsize + bsssize, stacksize,
|
|
|
114 |
USER_THREAD, 127, false);
|
|
|
115 |
reownalloc(image, thread);
|
|
|
116 |
thread_resume(thread);
|
|
|
117 |
return thread;
|
| 90 |
theseven |
118 |
}
|