1223695Sdfr/*-
2223695Sdfr * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3223695Sdfr * All rights reserved.
4223695Sdfr *
5223695Sdfr * Redistribution and use in source and binary forms, with or without
6223695Sdfr * modification, are permitted provided that the following conditions
7223695Sdfr * are met:
8223695Sdfr * 1. Redistributions of source code must retain the above copyright
9223695Sdfr *    notice, this list of conditions and the following disclaimer.
10223695Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11223695Sdfr *    notice, this list of conditions and the following disclaimer in the
12223695Sdfr *    documentation and/or other materials provided with the distribution.
13223695Sdfr *
14223695Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15223695Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16223695Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17223695Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18223695Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19223695Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20223695Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21223695Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22223695Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23223695Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24223695Sdfr * SUCH DAMAGE.
25223695Sdfr */
26223695Sdfr
27223695Sdfr#include <sys/cdefs.h>
28223695Sdfr__FBSDID("$FreeBSD: stable/11/stand/userboot/userboot/elf32_freebsd.c 261504 2014-02-05 04:39:03Z jhb $");
29223695Sdfr
30223695Sdfr#include <sys/param.h>
31223695Sdfr#include <sys/exec.h>
32223695Sdfr#include <sys/linker.h>
33223695Sdfr#include <string.h>
34247047Skib#define	_MACHINE_ELF_WANT_32BIT
35223695Sdfr#include <i386/include/bootinfo.h>
36223695Sdfr#include <i386/include/elf.h>
37223695Sdfr#include <stand.h>
38223695Sdfr
39223695Sdfr#include "bootstrap.h"
40223695Sdfr#include "libuserboot.h"
41223695Sdfr
42223695Sdfrstatic int	elf32_exec(struct preloaded_file *amp);
43223695Sdfrstatic int	elf32_obj_exec(struct preloaded_file *amp);
44223695Sdfr
45223695Sdfrstruct file_format i386_elf = { elf32_loadfile, elf32_exec };
46223695Sdfrstruct file_format i386_elf_obj = { elf32_obj_loadfile, elf32_obj_exec };
47223695Sdfr
48261504Sjhb#define	GUEST_STACK	0x1000		/* Initial stack base */
49261504Sjhb#define	GUEST_GDT	0x3000		/* Address of initial GDT */
50261504Sjhb
51223695Sdfr/*
52223695Sdfr * There is an ELF kernel and one or more ELF modules loaded.
53223695Sdfr * We wish to start executing the kernel image, so make such
54223695Sdfr * preparations as are required, and do so.
55223695Sdfr */
56223695Sdfrstatic int
57223695Sdfrelf32_exec(struct preloaded_file *fp)
58223695Sdfr{
59223695Sdfr	struct file_metadata	*md;
60223695Sdfr	Elf_Ehdr 		*ehdr;
61223695Sdfr	vm_offset_t		entry, bootinfop, modulep, kernend;
62223695Sdfr	int			boothowto, err, bootdev;
63261504Sjhb	uint32_t		stack[1024], *sp;
64223695Sdfr
65223695Sdfr
66223695Sdfr	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
67223695Sdfr		return(EFTYPE);
68223695Sdfr	ehdr = (Elf_Ehdr *)&(md->md_data);
69223695Sdfr
70223695Sdfr	err = bi_load32(fp->f_args, &boothowto, &bootdev, &bootinfop, &modulep, &kernend);
71223695Sdfr	if (err != 0)
72223695Sdfr		return(err);
73223695Sdfr	entry = ehdr->e_entry & 0xffffff;
74223695Sdfr
75223695Sdfr#ifdef DEBUG
76223695Sdfr	printf("Start @ 0x%lx ...\n", entry);
77223695Sdfr#endif
78223695Sdfr
79223695Sdfr	dev_cleanup();
80223695Sdfr
81223695Sdfr	/*
82223695Sdfr	 * Build a scratch stack at physical 0x1000
83223695Sdfr	 */
84261504Sjhb	memset(stack, 0, sizeof(stack));
85261504Sjhb	sp = (uint32_t *)((char *)stack + sizeof(stack));
86261504Sjhb	*--sp = kernend;
87261504Sjhb	*--sp = modulep;
88261504Sjhb	*--sp = bootinfop;
89261504Sjhb	*--sp = 0;
90261504Sjhb	*--sp = 0;
91261504Sjhb	*--sp = 0;
92261504Sjhb	*--sp = bootdev;
93261504Sjhb	*--sp = boothowto;
94261504Sjhb
95261504Sjhb	/*
96261504Sjhb	 * Fake return address to mimic "new" boot blocks.  For more
97261504Sjhb	 * details see recover_bootinfo in locore.S.
98261504Sjhb	 */
99261504Sjhb	*--sp = 0xbeefface;
100261504Sjhb	CALLBACK(copyin, stack, GUEST_STACK, sizeof(stack));
101261504Sjhb	CALLBACK(setreg, 4, (char *)sp - (char *)stack + GUEST_STACK);
102261504Sjhb
103261504Sjhb	CALLBACK(setgdt, GUEST_GDT, 8 * 4 - 1);
104261504Sjhb
105223695Sdfr        CALLBACK(exec, entry);
106223695Sdfr
107223695Sdfr	panic("exec returned");
108223695Sdfr}
109223695Sdfr
110223695Sdfrstatic int
111223695Sdfrelf32_obj_exec(struct preloaded_file *fp)
112223695Sdfr{
113223695Sdfr	return (EFTYPE);
114223695Sdfr}
115