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
35
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <inttypes.h>
40#include <string.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <errno.h>
44#include <sys/stat.h>
45#include <elf.h>
46#include <console.h>
47#include <dprintf.h>
48
49#include <syslinux/loadfile.h>
50#include <syslinux/movebits.h>
51#include <syslinux/bootpm.h>
52
53
54#define MIN_STACK 512
55
56static inline void error(const char *msg)
57{
58 fputs(msg, stderr);
59}
60
61int boot_raw(void *ptr, size_t len, addr_t where, char **argv)
62{
63 struct syslinux_movelist *ml = NULL;
64 struct syslinux_memmap *mmap = NULL, *amap = NULL;
65 struct syslinux_pm_regs regs;
66 int argc;
67 addr_t argsize;
68 char **argp;
69 addr_t lstart, llen;
70 char *stack_frame = NULL;
71 addr_t stack_frame_size;
72 addr_t stack_pointer;
73 uint32_t *spp;
74 char *sfp;
75 addr_t sfa;
76
77 memset(®s, 0, sizeof regs);
78
79 mmap = syslinux_memory_map();
80 amap = syslinux_dup_memmap(mmap);
81 if (!mmap || !amap)
82 goto bail;
83
84#if DEBUG
85 dprintf("Initial memory map:\n");
86 syslinux_dump_memmap(stdout, mmap);
87#endif
88
89 dprintf("Segment at 0x%08x len 0x%08x\n", where, len);
90
91 if (syslinux_memmap_type(amap, where, len) != SMT_FREE) {
92 printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
93 where, len);
94 goto bail;
95 }
96
97
98 if (syslinux_add_memmap(&amap, where, len, SMT_ALLOC))
99 goto bail;
100
101
102 if (syslinux_add_movelist(&ml, where, (addr_t) ptr, len))
103 goto bail;
104
105
106
107 argsize = argc = 0;
108 for (argp = argv; *argp; argp++) {
109 dprintf("argv[%2d] = \"%s\"\n", argc, *argp);
110 argc++;
111 argsize += strlen(*argp) + 1;
112 }
113
114
115
116 stack_frame_size = argsize + argc * sizeof(char *) + 5 * sizeof(long);
117 stack_frame_size = (stack_frame_size + 15) & ~15;
118 stack_frame = calloc(stack_frame_size, 1);
119 if (!stack_frame)
120 goto bail;
121
122#if DEBUG
123 dprintf("Right before syslinux_memmap_largest()...\n");
124 syslinux_dump_memmap(stdout, amap);
125#endif
126
127 if (syslinux_memmap_largest(amap, SMT_FREE, &lstart, &llen))
128 goto bail;
129
130 if (llen < stack_frame_size + MIN_STACK + 16)
131 goto bail;
132
133
134 stack_pointer = (lstart + llen - stack_frame_size) & ~15;
135
136 dprintf("Stack frame at 0x%08x len 0x%08x\n",
137 stack_pointer, stack_frame_size);
138
139
140
141
142 spp = (uint32_t *) stack_frame;
143 sfp = stack_frame + argc * sizeof(char *) + 5 * sizeof(long);
144 sfa = stack_pointer + argc * sizeof(char *) + 5 * sizeof(long);
145
146 *spp++ = argc;
147 for (argp = argv; *argp; argp++) {
148 int bytes = strlen(*argp) + 1;
149 *spp++ = sfa;
150 memcpy(sfp, *argp, bytes);
151 sfp += bytes;
152 sfa += bytes;
153 }
154
155
156
157#if DEBUG
158 if (syslinux_memmap_type(amap, stack_pointer, stack_frame_size)
159 != SMT_FREE) {
160 dprintf("Stack frame area not free (how did that happen?)!\n");
161 goto bail;
162 }
163#endif
164
165 if (syslinux_add_memmap(&amap, stack_pointer, stack_frame_size, SMT_ALLOC))
166 goto bail;
167
168 if (syslinux_add_movelist(&ml, stack_pointer, (addr_t) stack_frame,
169 stack_frame_size))
170 goto bail;
171
172 memset(®s, 0, sizeof regs);
173 regs.eip = where;
174 regs.esp = stack_pointer;
175
176#if DEBUG
177 dprintf("Final memory map:\n");
178 syslinux_dump_memmap(stdout, mmap);
179
180 dprintf("Final available map:\n");
181 syslinux_dump_memmap(stdout, amap);
182
183 dprintf("Movelist:\n");
184 syslinux_dump_movelist(stdout, ml);
185#endif
186
187
188 fputs("Booting...\n", stdout);
189 syslinux_shuffle_boot_pm(ml, mmap, 0, ®s);
190
191bail:
192 if (stack_frame)
193 free(stack_frame);
194 syslinux_free_memmap(amap);
195 syslinux_free_memmap(mmap);
196 syslinux_free_movelist(ml);
197
198 return -1;
199}
200
201int main(int argc, char *argv[])
202{
203 void *data;
204 size_t data_len;
205 addr_t where;
206
207 openconsole(&dev_null_r, &dev_stdcon_w);
208
209 if (argc < 3) {
210 error("Usage: pmload.c32 bin_file address arguments...\n");
211 return 1;
212 }
213
214 where = strtoul(argv[2], NULL, 0);
215
216 if (loadfile(argv[1], &data, &data_len)) {
217 error("Unable to load file\n");
218 return 1;
219 }
220
221 boot_raw(data, data_len, where, &argv[1]);
222 error("Failed to boot, probably insufficient memory\n");
223 return 1;
224}
225