Adding upstream version 4.00~pre61+dfsg.
[syslinux-debian/hramrach.git] / com32 / modules / pmload.c
blob7a0e193f47b67041e1cd867b25c4088a70600535
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
12 * conditions:
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 * ----------------------------------------------------------------------- */
29 * pmload.c
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...]
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>
48 #include <syslinux/loadfile.h>
49 #include <syslinux/movebits.h>
50 #include <syslinux/bootpm.h>
52 /* If we don't have this much memory for the stack, signal failure */
53 #define MIN_STACK 512
55 #define DEBUG 0
56 #if DEBUG
57 # define dprintf printf
58 #else
59 # define dprintf(f, ...) ((void)0)
60 #endif
62 static inline void error(const char *msg)
64 fputs(msg, stderr);
67 int boot_raw(void *ptr, size_t len, addr_t where, char **argv)
69 struct syslinux_movelist *ml = NULL;
70 struct syslinux_memmap *mmap = NULL, *amap = NULL;
71 struct syslinux_pm_regs regs;
72 int argc;
73 addr_t argsize;
74 char **argp;
75 addr_t lstart, llen;
76 char *stack_frame = NULL;
77 addr_t stack_frame_size;
78 addr_t stack_pointer;
79 uint32_t *spp;
80 char *sfp;
81 addr_t sfa;
83 memset(&regs, 0, sizeof regs);
85 mmap = syslinux_memory_map();
86 amap = syslinux_dup_memmap(mmap);
87 if (!mmap || !amap)
88 goto bail;
90 #if DEBUG
91 dprintf("Initial memory map:\n");
92 syslinux_dump_memmap(stdout, mmap);
93 #endif
95 dprintf("Segment at 0x%08x len 0x%08x\n", where, len);
97 if (syslinux_memmap_type(amap, where, len) != SMT_FREE) {
98 printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
99 where, len);
100 goto bail; /* Memory region unavailable */
103 /* Mark this region as allocated in the available map */
104 if (syslinux_add_memmap(&amap, where, len, SMT_ALLOC))
105 goto bail;
107 /* Data present region. Create a move entry for it. */
108 if (syslinux_add_movelist(&ml, where, (addr_t) ptr, len))
109 goto bail;
111 /* Create the invocation record (initial stack frame) */
113 argsize = argc = 0;
114 for (argp = argv; *argp; argp++) {
115 dprintf("argv[%2d] = \"%s\"\n", argc, *argp);
116 argc++;
117 argsize += strlen(*argp) + 1;
120 /* We need the argument strings, argument pointers,
121 argc, plus four zero-word terminators. */
122 stack_frame_size = argsize + argc * sizeof(char *) + 5 * sizeof(long);
123 stack_frame_size = (stack_frame_size + 15) & ~15;
124 stack_frame = calloc(stack_frame_size, 1);
125 if (!stack_frame)
126 goto bail;
128 #if DEBUG
129 dprintf("Right before syslinux_memmap_largest()...\n");
130 syslinux_dump_memmap(stdout, amap);
131 #endif
133 if (syslinux_memmap_largest(amap, SMT_FREE, &lstart, &llen))
134 goto bail; /* NO free memory?! */
136 if (llen < stack_frame_size + MIN_STACK + 16)
137 goto bail; /* Insufficient memory */
139 /* Initial stack pointer address */
140 stack_pointer = (lstart + llen - stack_frame_size) & ~15;
142 dprintf("Stack frame at 0x%08x len 0x%08x\n",
143 stack_pointer, stack_frame_size);
145 /* Create the stack frame. sfp is the pointer in current memory for
146 the next argument string, sfa is the address in its final resting place.
147 spp is the pointer into the argument array in current memory. */
148 spp = (uint32_t *) stack_frame;
149 sfp = stack_frame + argc * sizeof(char *) + 5 * sizeof(long);
150 sfa = stack_pointer + argc * sizeof(char *) + 5 * sizeof(long);
152 *spp++ = argc;
153 for (argp = argv; *argp; argp++) {
154 int bytes = strlen(*argp) + 1; /* Including final null */
155 *spp++ = sfa;
156 memcpy(sfp, *argp, bytes);
157 sfp += bytes;
158 sfa += bytes;
160 /* Zero fields are aready taken care of by calloc() */
162 /* ... and we'll want to move it into the right place... */
163 #if DEBUG
164 if (syslinux_memmap_type(amap, stack_pointer, stack_frame_size)
165 != SMT_FREE) {
166 dprintf("Stack frame area not free (how did that happen?)!\n");
167 goto bail; /* Memory region unavailable */
169 #endif
171 if (syslinux_add_memmap(&amap, stack_pointer, stack_frame_size, SMT_ALLOC))
172 goto bail;
174 if (syslinux_add_movelist(&ml, stack_pointer, (addr_t) stack_frame,
175 stack_frame_size))
176 goto bail;
178 memset(&regs, 0, sizeof regs);
179 regs.eip = where;
180 regs.esp = stack_pointer;
182 #if DEBUG
183 dprintf("Final memory map:\n");
184 syslinux_dump_memmap(stdout, mmap);
186 dprintf("Final available map:\n");
187 syslinux_dump_memmap(stdout, amap);
189 dprintf("Movelist:\n");
190 syslinux_dump_movelist(stdout, ml);
191 #endif
193 /* This should not return... */
194 fputs("Booting...\n", stdout);
195 syslinux_shuffle_boot_pm(ml, mmap, 0, &regs);
197 bail:
198 if (stack_frame)
199 free(stack_frame);
200 syslinux_free_memmap(amap);
201 syslinux_free_memmap(mmap);
202 syslinux_free_movelist(ml);
204 return -1;
207 int main(int argc, char *argv[])
209 void *data;
210 size_t data_len;
211 addr_t where;
213 openconsole(&dev_null_r, &dev_stdcon_w);
215 if (argc < 3) {
216 error("Usage: pmload.c32 bin_file address arguments...\n");
217 return 1;
220 where = strtoul(argv[2], NULL, 0);
222 if (loadfile(argv[1], &data, &data_len)) {
223 error("Unable to load file\n");
224 return 1;
227 boot_raw(data, data_len, where, &argv[1]);
228 error("Failed to boot, probably insufficient memory\n");
229 return 1;