176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- *
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   Permission is hereby granted, free of charge, to any person
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   obtaining a copy of this software and associated documentation
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   files (the "Software"), to deal in the Software without
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   restriction, including without limitation the rights to use,
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   copy, modify, merge, publish, distribute, sublicense, and/or
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   sell copies of the Software, and to permit persons to whom
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   the Software is furnished to do so, subject to the following
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   conditions:
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   The above copyright notice and this permission notice shall
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   be included in all copies or substantial portions of the Software.
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *   OTHER DEALINGS IN THE SOFTWARE.
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * elf.c
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Module to load a protected-mode ELF kernel
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h>
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h>
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <inttypes.h>
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <fcntl.h>
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <unistd.h>
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h>
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <minmax.h>
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/stat.h>
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <elf.h>
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <console.h>
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <dprintf.h>
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/loadfile.h>
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/movebits.h>
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <syslinux/bootpm.h>
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* If we don't have this much memory for the stack, signal failure */
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define MIN_STACK	512
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic inline void error(const char *msg)
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fputs(msg, stderr);
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint boot_elf(void *ptr, size_t len, char **argv)
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *cptr = ptr;
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    Elf32_Ehdr *eh = ptr;
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    Elf32_Phdr *ph;
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    unsigned int i;
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct syslinux_movelist *ml = NULL;
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct syslinux_memmap *mmap = NULL, *amap = NULL;
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    struct syslinux_pm_regs regs;
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int argc;
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    addr_t argsize;
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char **argp;
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    addr_t lstart, llen;
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *stack_frame = NULL;
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    addr_t stack_frame_size;
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    addr_t stack_pointer;
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    uint32_t *spp;
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char *sfp;
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    addr_t sfa;
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memset(&regs, 0, sizeof regs);
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * Note: mmap is the memory map (containing free and zeroed regions)
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * needed by syslinux_shuffle_boot_pm(); amap is a map where we keep
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * track ourselves which target memory ranges have already been
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * allocated.
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     */
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (len < sizeof(Elf32_Ehdr))
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Must be ELF, 32-bit, littleendian, version 1 */
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (memcmp(eh->e_ident, "\x7f" "ELF\1\1\1", 6))
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Is this a worthwhile test?  In particular x86-64 normally
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       would imply ELF64 support, which we could do as long as
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       the addresses are 32-bit addresses, and entry is 32 bits.
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       64-bit addresses would take a lot more work. */
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (eh->e_machine != EM_386 && eh->e_machine != EM_486 &&
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	eh->e_machine != EM_X86_64)
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (eh->e_version != EV_CURRENT)
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (eh->e_ehsize < sizeof(Elf32_Ehdr) || eh->e_ehsize >= len)
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (eh->e_phentsize < sizeof(Elf32_Phdr))
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!eh->e_phnum)
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (eh->e_phoff + eh->e_phentsize * eh->e_phnum > len)
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    mmap = syslinux_memory_map();
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    amap = syslinux_dup_memmap(mmap);
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!mmap || !amap)
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dprintf("Initial memory map:\n");
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_dump_memmap(mmap);
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ph = (Elf32_Phdr *) (cptr + eh->e_phoff);
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (i = 0; i < eh->e_phnum; i++) {
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	if (ph->p_type == PT_LOAD || ph->p_type == PT_PHDR) {
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* This loads at p_paddr, which is arguably the correct semantics.
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	       The SysV spec says that SysV loads at p_vaddr (and thus Linux does,
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	       too); that is, however, a major brainfuckage in the spec. */
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    addr_t addr = ph->p_paddr;
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    addr_t msize = ph->p_memsz;
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    addr_t dsize = min(msize, ph->p_filesz);
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    dprintf("Segment at 0x%08x data 0x%08x len 0x%08x\n",
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    addr, dsize, msize);
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (syslinux_memmap_type(amap, addr, msize) != SMT_FREE) {
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		printf("Memory segment at 0x%08x (len 0x%08x) is unavailable\n",
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		       addr, msize);
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		goto bail;	/* Memory region unavailable */
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Mark this region as allocated in the available map */
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (syslinux_add_memmap(&amap, addr, dsize, SMT_ALLOC))
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		goto bail;
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (ph->p_filesz) {
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		/* Data present region.  Create a move entry for it. */
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if (syslinux_add_movelist
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    (&ml, addr, (addr_t) cptr + ph->p_offset, dsize))
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    goto bail;
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    if (msize > dsize) {
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		/* Zero-filled region.  Mark as a zero region in the memory map. */
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		if (syslinux_add_memmap
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    (&mmap, addr + dsize, msize - dsize, SMT_ZERO))
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		    goto bail;
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    }
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	} else {
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    /* Ignore this program header */
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	}
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	ph = (Elf32_Phdr *) ((char *)ph + eh->e_phentsize);
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Create the invocation record (initial stack frame) */
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    argsize = argc = 0;
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (argp = argv; *argp; argp++) {
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	dprintf("argv[%2d] = \"%s\"\n", argc, *argp);
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	argc++;
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	argsize += strlen(*argp) + 1;
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* We need the argument strings, argument pointers,
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       argc, plus four zero-word terminators. */
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    stack_frame_size = argsize + argc * sizeof(char *) + 5 * sizeof(long);
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    stack_frame_size = (stack_frame_size + 15) & ~15;
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    stack_frame = calloc(stack_frame_size, 1);
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!stack_frame)
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dprintf("Right before syslinux_memmap_largest()...\n");
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_dump_memmap(amap);
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (syslinux_memmap_largest(amap, SMT_FREE, &lstart, &llen))
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;		/* NO free memory?! */
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (llen < stack_frame_size + MIN_STACK + 16)
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;		/* Insufficient memory  */
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Initial stack pointer address */
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    stack_pointer = (lstart + llen - stack_frame_size) & ~15;
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dprintf("Stack frame at 0x%08x len 0x%08x\n",
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    stack_pointer, stack_frame_size);
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Create the stack frame.  sfp is the pointer in current memory for
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       the next argument string, sfa is the address in its final resting place.
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       spp is the pointer into the argument array in current memory. */
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    spp = (uint32_t *) stack_frame;
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    sfp = stack_frame + argc * sizeof(char *) + 5 * sizeof(long);
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    sfa = stack_pointer + argc * sizeof(char *) + 5 * sizeof(long);
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    *spp++ = argc;
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (argp = argv; *argp; argp++) {
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	int bytes = strlen(*argp) + 1;	/* Including final null */
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	*spp++ = sfa;
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	memcpy(sfp, *argp, bytes);
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	sfp += bytes;
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	sfa += bytes;
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* Zero fields are aready taken care of by calloc() */
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* ... and we'll want to move it into the right place... */
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#if DEBUG
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (syslinux_memmap_type(amap, stack_pointer, stack_frame_size)
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	!= SMT_FREE) {
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	dprintf("Stack frame area not free (how did that happen?)!\n");
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;		/* Memory region unavailable */
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (syslinux_add_memmap(&amap, stack_pointer, stack_frame_size, SMT_ALLOC))
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (syslinux_add_movelist(&ml, stack_pointer, (addr_t) stack_frame,
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman			      stack_frame_size))
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	goto bail;
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    memset(&regs, 0, sizeof regs);
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    regs.eip = eh->e_entry;
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    regs.esp = stack_pointer;
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dprintf("Final memory map:\n");
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_dump_memmap(mmap);
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dprintf("Final available map:\n");
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_dump_memmap(amap);
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    dprintf("Movelist:\n");
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_dump_movelist(ml);
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* This should not return... */
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    fputs("Booting...\n", stdout);
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_shuffle_boot_pm(ml, mmap, 0, &regs);
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanbail:
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (stack_frame)
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	free(stack_frame);
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_free_memmap(amap);
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_free_memmap(mmap);
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    syslinux_free_movelist(ml);
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return -1;
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint main(int argc, char *argv[])
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    void *data;
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    size_t data_len;
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (argc < 2) {
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	error("Usage: elf.c32 elf_file arguments...\n");
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 1;
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (zloadfile(argv[1], &data, &data_len)) {
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	error("Unable to load file\n");
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 1;
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    boot_elf(data, data_len, &argv[1]);
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    error("Invalid ELF file or insufficient memory\n");
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
280