elf64_freebsd.c revision 163708
121259Swollman/*-
221259Swollman * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
321259Swollman * All rights reserved.
421259Swollman *
521259Swollman * Redistribution and use in source and binary forms, with or without
621259Swollman * modification, are permitted provided that the following conditions
721259Swollman * are met:
821259Swollman * 1. Redistributions of source code must retain the above copyright
921259Swollman *    notice, this list of conditions and the following disclaimer.
1021259Swollman * 2. Redistributions in binary form must reproduce the above copyright
1121259Swollman *    notice, this list of conditions and the following disclaimer in the
1221259Swollman *    documentation and/or other materials provided with the distribution.
1321259Swollman *
1421259Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1521259Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1621259Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1721259Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1821259Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1921259Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2021259Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2121259Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2221259Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2321259Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2421259Swollman * SUCH DAMAGE.
2521259Swollman */
2621259Swollman
2721259Swollman#include <sys/cdefs.h>
2821259Swollman__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/elf64_freebsd.c 163708 2006-10-26 20:04:22Z ru $");
2921259Swollman
3050477Speter#define __ELF_WORD_SIZE 64
3121259Swollman#include <sys/param.h>
3221259Swollman#include <sys/exec.h>
3321259Swollman#include <sys/linker.h>
3421259Swollman#include <string.h>
3521259Swollman#include <machine/bootinfo.h>
3621259Swollman#include <machine/elf.h>
3721259Swollman#include <stand.h>
3821259Swollman
3921259Swollman#include "bootstrap.h"
4021259Swollman#include "libi386.h"
4121259Swollman#include "btxv86.h"
4221259Swollman
4321259Swollmanstatic int	elf64_exec(struct preloaded_file *amp);
4421259Swollmanstatic int	elf64_obj_exec(struct preloaded_file *amp);
4521259Swollman
4621259Swollmanstruct file_format amd64_elf = { elf64_loadfile, elf64_exec };
4721259Swollmanstruct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec };
4821259Swollman
4921259Swollman#define PG_V	0x001
5021259Swollman#define PG_RW	0x002
51108533Sschweikh#define PG_U	0x004
5221259Swollman#define PG_PS	0x080
5321259Swollman
5421259Swollmantypedef u_int64_t p4_entry_t;
5521259Swollmantypedef u_int64_t p3_entry_t;
56108533Sschweikhtypedef u_int64_t p2_entry_t;
5721259Swollmanextern p4_entry_t PT4[];
5821259Swollmanextern p3_entry_t PT3[];
5921259Swollmanextern p2_entry_t PT2[];
6021259Swollman
6121259Swollmanu_int32_t entry_hi;
6221259Swollmanu_int32_t entry_lo;
6321259Swollman
6421259Swollmanextern void amd64_tramp();
6521259Swollman
6683366Sjulian/*
6721259Swollman * There is an ELF kernel and one or more ELF modules loaded.
6885074Sru * We wish to start executing the kernel image, so make such
6921259Swollman * preparations as are required, and do so.
7021259Swollman */
7121259Swollmanstatic int
7221259Swollmanelf64_exec(struct preloaded_file *fp)
7321259Swollman{
7421259Swollman    struct file_metadata	*md;
7569224Sjlemon    Elf_Ehdr 			*ehdr;
7669152Sjlemon    vm_offset_t			modulep, kernend;
77126264Smlaier    int				err;
7869224Sjlemon    int				i;
7974914Sjhb
8074914Sjhb    if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
8183130Sjlemon	return(EFTYPE);			/* XXX actually EFUCKUP */
8269152Sjlemon    ehdr = (Elf_Ehdr *)&(md->md_data);
83121816Sbrooks
84121816Sbrooks    err = bi_load64(fp->f_args, &modulep, &kernend);
8560938Sjake    if (err != 0)
8660938Sjake	return(err);
8760938Sjake
8872084Sphk    bzero(PT4, PAGE_SIZE);
8921259Swollman    bzero(PT3, PAGE_SIZE);
9021259Swollman    bzero(PT2, PAGE_SIZE);
9121259Swollman
9221259Swollman    /*
9321259Swollman     * This is kinda brutal, but every single 1GB VM memory segment points to
9421259Swollman     * the same first 1GB of physical memory.  But it is more than adequate.
9521259Swollman     */
9621259Swollman    for (i = 0; i < 512; i++) {
9721259Swollman	/* Each slot of the level 4 pages points to the same level 3 page */
9821259Swollman	PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]);
9969152Sjlemon	PT4[i] |= PG_V | PG_RW | PG_U;
10021259Swollman
10121259Swollman	/* Each slot of the level 3 pages points to the same level 2 page */
10221259Swollman	PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]);
10321259Swollman	PT3[i] |= PG_V | PG_RW | PG_U;
10421259Swollman
10521259Swollman	/* The level 2 page slots are mapped with 2MB pages for 1GB. */
10621259Swollman	PT2[i] = i * (2 * 1024 * 1024);
10784380Smjacob	PT2[i] |= PG_V | PG_RW | PG_PS | PG_U;
10884380Smjacob    }
10984380Smjacob
11084380Smjacob    entry_lo = ehdr->e_entry & 0xffffffff;
11186797Sluigi    entry_hi = (ehdr->e_entry >> 32) & 0xffffffff;
11286797Sluigi#ifdef DEBUG
11386797Sluigi    printf("Start @ %#llx ...\n", ehdr->e_entry);
11486797Sluigi#endif
11586797Sluigi
11686797Sluigi    dev_cleanup();
11786797Sluigi    __exec((void *)VTOP(amd64_tramp), modulep, kernend);
11886797Sluigi
11986797Sluigi    panic("exec returned");
12086797Sluigi}
12186797Sluigi
12286797Sluigistatic int
12386797Sluigielf64_obj_exec(struct preloaded_file *fp)
12486797Sluigi{
12586797Sluigi	return (EFTYPE);
12684380Smjacob}
12721259Swollman