1 /* ----------------------------------------------------------------------- *
3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
26 * ----------------------------------------------------------------------- */
31 * Load a binary file and run it in protected mode. We give it
32 * an ELF-style invocation record, becase, why not?
34 * Usage: pmload.c32 filename address [arguments...]
49 #include <syslinux/loadfile.h>
50 #include <syslinux/movebits.h>
51 #include <syslinux/bootpm.h>
53 /* If we don't have this much memory for the stack, signal failure */
56 static inline void error(const char *msg
)
61 int boot_raw(void *ptr
, size_t len
, addr_t where
, char **argv
)
63 struct syslinux_movelist
*ml
= NULL
;
64 struct syslinux_memmap
*mmap
= NULL
, *amap
= NULL
;
65 struct syslinux_pm_regs regs
;
70 char *stack_frame
= NULL
;
71 addr_t stack_frame_size
;
77 memset(®s
, 0, sizeof regs
);
79 mmap
= syslinux_memory_map();
80 amap
= syslinux_dup_memmap(mmap
);
85 dprintf("Initial memory map:\n");
86 syslinux_dump_memmap(stdout
, mmap
);
89 dprintf("Segment at 0x%08x len 0x%08x\n", where
, len
);
91 if (syslinux_memmap_type(amap
, where
, len
) != SMT_FREE
) {
92 printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
94 goto bail
; /* Memory region unavailable */
97 /* Mark this region as allocated in the available map */
98 if (syslinux_add_memmap(&amap
, where
, len
, SMT_ALLOC
))
101 /* Data present region. Create a move entry for it. */
102 if (syslinux_add_movelist(&ml
, where
, (addr_t
) ptr
, len
))
105 /* Create the invocation record (initial stack frame) */
108 for (argp
= argv
; *argp
; argp
++) {
109 dprintf("argv[%2d] = \"%s\"\n", argc
, *argp
);
111 argsize
+= strlen(*argp
) + 1;
114 /* We need the argument strings, argument pointers,
115 argc, plus four zero-word terminators. */
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);
123 dprintf("Right before syslinux_memmap_largest()...\n");
124 syslinux_dump_memmap(stdout
, amap
);
127 if (syslinux_memmap_largest(amap
, SMT_FREE
, &lstart
, &llen
))
128 goto bail
; /* NO free memory?! */
130 if (llen
< stack_frame_size
+ MIN_STACK
+ 16)
131 goto bail
; /* Insufficient memory */
133 /* Initial stack pointer address */
134 stack_pointer
= (lstart
+ llen
- stack_frame_size
) & ~15;
136 dprintf("Stack frame at 0x%08x len 0x%08x\n",
137 stack_pointer
, stack_frame_size
);
139 /* Create the stack frame. sfp is the pointer in current memory for
140 the next argument string, sfa is the address in its final resting place.
141 spp is the pointer into the argument array in current memory. */
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);
147 for (argp
= argv
; *argp
; argp
++) {
148 int bytes
= strlen(*argp
) + 1; /* Including final null */
150 memcpy(sfp
, *argp
, bytes
);
154 /* Zero fields are aready taken care of by calloc() */
156 /* ... and we'll want to move it into the right place... */
158 if (syslinux_memmap_type(amap
, stack_pointer
, stack_frame_size
)
160 dprintf("Stack frame area not free (how did that happen?)!\n");
161 goto bail
; /* Memory region unavailable */
165 if (syslinux_add_memmap(&amap
, stack_pointer
, stack_frame_size
, SMT_ALLOC
))
168 if (syslinux_add_movelist(&ml
, stack_pointer
, (addr_t
) stack_frame
,
172 memset(®s
, 0, sizeof regs
);
174 regs
.esp
= stack_pointer
;
177 dprintf("Final memory map:\n");
178 syslinux_dump_memmap(stdout
, mmap
);
180 dprintf("Final available map:\n");
181 syslinux_dump_memmap(stdout
, amap
);
183 dprintf("Movelist:\n");
184 syslinux_dump_movelist(stdout
, ml
);
187 /* This should not return... */
188 fputs("Booting...\n", stdout
);
189 syslinux_shuffle_boot_pm(ml
, mmap
, 0, ®s
);
194 syslinux_free_memmap(amap
);
195 syslinux_free_memmap(mmap
);
196 syslinux_free_movelist(ml
);
201 int main(int argc
, char *argv
[])
207 openconsole(&dev_null_r
, &dev_stdcon_w
);
210 error("Usage: pmload.c32 bin_file address arguments...\n");
214 where
= strtoul(argv
[2], NULL
, 0);
216 if (loadfile(argv
[1], &data
, &data_len
)) {
217 error("Unable to load file\n");
221 boot_raw(data
, data_len
, where
, &argv
[1]);
222 error("Failed to boot, probably insufficient memory\n");