1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <inttypes.h>
37#include <string.h>
38#include <fcntl.h>
39#include <unistd.h>
40#include <errno.h>
41#include <minmax.h>
42#include <sys/stat.h>
43#include <elf.h>
44#include <console.h>
45#include <dprintf.h>
46
47#include <syslinux/loadfile.h>
48#include <syslinux/movebits.h>
49#include <syslinux/bootpm.h>
50
51
52#define MIN_STACK 512
53
54static inline void error(const char *msg)
55{
56 fputs(msg, stderr);
57}
58
59int boot_elf(void *ptr, size_t len, char **argv)
60{
61 char *cptr = ptr;
62 Elf32_Ehdr *eh = ptr;
63 Elf32_Phdr *ph;
64 unsigned int i;
65 struct syslinux_movelist *ml = NULL;
66 struct syslinux_memmap *mmap = NULL, *amap = NULL;
67 struct syslinux_pm_regs regs;
68 int argc;
69 addr_t argsize;
70 char **argp;
71 addr_t lstart, llen;
72 char *stack_frame = NULL;
73 addr_t stack_frame_size;
74 addr_t stack_pointer;
75 uint32_t *spp;
76 char *sfp;
77 addr_t sfa;
78
79 memset(®s, 0, sizeof regs);
80
81
82
83
84
85
86
87
88 if (len < sizeof(Elf32_Ehdr))
89 goto bail;
90
91
92 if (memcmp(eh->e_ident, "\x7f" "ELF\1\1\1", 6))
93 goto bail;
94
95
96
97
98
99 if (eh->e_machine != EM_386 && eh->e_machine != EM_486 &&
100 eh->e_machine != EM_X86_64)
101 goto bail;
102
103 if (eh->e_version != EV_CURRENT)
104 goto bail;
105
106 if (eh->e_ehsize < sizeof(Elf32_Ehdr) || eh->e_ehsize >= len)
107 goto bail;
108
109 if (eh->e_phentsize < sizeof(Elf32_Phdr))
110 goto bail;
111
112 if (!eh->e_phnum)
113 goto bail;
114
115 if (eh->e_phoff + eh->e_phentsize * eh->e_phnum > len)
116 goto bail;
117
118 mmap = syslinux_memory_map();
119 amap = syslinux_dup_memmap(mmap);
120 if (!mmap || !amap)
121 goto bail;
122
123 dprintf("Initial memory map:\n");
124 syslinux_dump_memmap(mmap);
125
126 ph = (Elf32_Phdr *) (cptr + eh->e_phoff);
127
128 for (i = 0; i < eh->e_phnum; i++) {
129 if (ph->p_type == PT_LOAD || ph->p_type == PT_PHDR) {
130
131
132
133 addr_t addr = ph->p_paddr;
134 addr_t msize = ph->p_memsz;
135 addr_t dsize = min(msize, ph->p_filesz);
136
137 dprintf("Segment at 0x%08x data 0x%08x len 0x%08x\n",
138 addr, dsize, msize);
139
140 if (syslinux_memmap_type(amap, addr, msize) != SMT_FREE) {
141 printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
142 addr, msize);
143 goto bail;
144 }
145
146
147 if (syslinux_add_memmap(&amap, addr, dsize, SMT_ALLOC))
148 goto bail;
149
150 if (ph->p_filesz) {
151
152 if (syslinux_add_movelist
153 (&ml, addr, (addr_t) cptr + ph->p_offset, dsize))
154 goto bail;
155 }
156 if (msize > dsize) {
157
158 if (syslinux_add_memmap
159 (&mmap, addr + dsize, msize - dsize, SMT_ZERO))
160 goto bail;
161 }
162 } else {
163
164 }
165
166 ph = (Elf32_Phdr *) ((char *)ph + eh->e_phentsize);
167 }
168
169
170
171 argsize = argc = 0;
172 for (argp = argv; *argp; argp++) {
173 dprintf("argv[%2d] = \"%s\"\n", argc, *argp);
174 argc++;
175 argsize += strlen(*argp) + 1;
176 }
177
178
179
180 stack_frame_size = argsize + argc * sizeof(char *) + 5 * sizeof(long);
181 stack_frame_size = (stack_frame_size + 15) & ~15;
182 stack_frame = calloc(stack_frame_size, 1);
183 if (!stack_frame)
184 goto bail;
185
186 dprintf("Right before syslinux_memmap_largest()...\n");
187 syslinux_dump_memmap(amap);
188
189 if (syslinux_memmap_largest(amap, SMT_FREE, &lstart, &llen))
190 goto bail;
191
192 if (llen < stack_frame_size + MIN_STACK + 16)
193 goto bail;
194
195
196 stack_pointer = (lstart + llen - stack_frame_size) & ~15;
197
198 dprintf("Stack frame at 0x%08x len 0x%08x\n",
199 stack_pointer, stack_frame_size);
200
201
202
203
204 spp = (uint32_t *) stack_frame;
205 sfp = stack_frame + argc * sizeof(char *) + 5 * sizeof(long);
206 sfa = stack_pointer + argc * sizeof(char *) + 5 * sizeof(long);
207
208 *spp++ = argc;
209 for (argp = argv; *argp; argp++) {
210 int bytes = strlen(*argp) + 1;
211 *spp++ = sfa;
212 memcpy(sfp, *argp, bytes);
213 sfp += bytes;
214 sfa += bytes;
215 }
216
217
218
219#if DEBUG
220 if (syslinux_memmap_type(amap, stack_pointer, stack_frame_size)
221 != SMT_FREE) {
222 dprintf("Stack frame area not free (how did that happen?)!\n");
223 goto bail;
224 }
225#endif
226
227 if (syslinux_add_memmap(&amap, stack_pointer, stack_frame_size, SMT_ALLOC))
228 goto bail;
229
230 if (syslinux_add_movelist(&ml, stack_pointer, (addr_t) stack_frame,
231 stack_frame_size))
232 goto bail;
233
234 memset(®s, 0, sizeof regs);
235 regs.eip = eh->e_entry;
236 regs.esp = stack_pointer;
237
238 dprintf("Final memory map:\n");
239 syslinux_dump_memmap(mmap);
240
241 dprintf("Final available map:\n");
242 syslinux_dump_memmap(amap);
243
244 dprintf("Movelist:\n");
245 syslinux_dump_movelist(ml);
246
247
248 fputs("Booting...\n", stdout);
249 syslinux_shuffle_boot_pm(ml, mmap, 0, ®s);
250
251bail:
252 if (stack_frame)
253 free(stack_frame);
254 syslinux_free_memmap(amap);
255 syslinux_free_memmap(mmap);
256 syslinux_free_movelist(ml);
257
258 return -1;
259}
260
261int main(int argc, char *argv[])
262{
263 void *data;
264 size_t data_len;
265
266 openconsole(&dev_null_r, &dev_stdcon_w);
267
268 if (argc < 2) {
269 error("Usage: elf.c32 elf_file arguments...\n");
270 return 1;
271 }
272
273 if (zloadfile(argv[1], &data, &data_len)) {
274 error("Unable to load file\n");
275 return 1;
276 }
277
278 boot_elf(data, data_len, &argv[1]);
279 error("Invalid ELF file or insufficient memory\n");
280 return 1;
281}
282