From owner-svn-src-head@FreeBSD.ORG Wed Apr 7 18:16:05 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE080106566B; Wed, 7 Apr 2010 18:16:05 +0000 (UTC) (envelope-from rpaulo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id CC0BF8FC20; Wed, 7 Apr 2010 18:16:05 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o37IG5mj073360; Wed, 7 Apr 2010 18:16:05 GMT (envelope-from rpaulo@svn.freebsd.org) Received: (from rpaulo@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o37IG5Um073349; Wed, 7 Apr 2010 18:16:05 GMT (envelope-from rpaulo@svn.freebsd.org) Message-Id: <201004071816.o37IG5Um073349@svn.freebsd.org> From: Rui Paulo Date: Wed, 7 Apr 2010 18:16:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r206376 - head/sys/boot/i386/efi X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Apr 2010 18:16:06 -0000 Author: rpaulo Date: Wed Apr 7 18:16:05 2010 New Revision: 206376 URL: http://svn.freebsd.org/changeset/base/206376 Log: EFI boot loader for FreeBSD/i386. Doesn't boot a kernel yet, but it can read an ELF file from the EFI FAT partition. Added: head/sys/boot/i386/efi/ head/sys/boot/i386/efi/Makefile (contents, props changed) head/sys/boot/i386/efi/autoload.c (contents, props changed) head/sys/boot/i386/efi/bootinfo.c (contents, props changed) head/sys/boot/i386/efi/conf.c (contents, props changed) head/sys/boot/i386/efi/devicename.c (contents, props changed) head/sys/boot/i386/efi/efimd.c (contents, props changed) head/sys/boot/i386/efi/elf32_freebsd.c (contents, props changed) head/sys/boot/i386/efi/exec.c (contents, props changed) head/sys/boot/i386/efi/i386_copy.c (contents, props changed) head/sys/boot/i386/efi/ldscript.amd64 (contents, props changed) head/sys/boot/i386/efi/ldscript.i386 (contents, props changed) head/sys/boot/i386/efi/main.c (contents, props changed) head/sys/boot/i386/efi/reloc.c (contents, props changed) head/sys/boot/i386/efi/start.S (contents, props changed) head/sys/boot/i386/efi/version (contents, props changed) Added: head/sys/boot/i386/efi/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/Makefile Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,69 @@ +# $FreeBSD$ + +NO_MAN= +WITHOUT_SSP= +BUILDING_EFI= + +.include + +PROG= loader.sym +INTERNALPROG= + +# architecture-specific loader code +SRCS= main.c exec.c conf.c vers.c reloc.c start.S elf32_freebsd.c +SRCS+= i386_copy.c bootinfo.c autoload.c devicename.c efimd.c + +CFLAGS+= -I${.CURDIR}/../../efi/include +CFLAGS+= -I${.CURDIR}/../../efi/include/i386 + +.if ${MK_FORTH} != "no" +BOOT_FORTH= yes +CFLAGS+= -DBOOT_FORTH +CFLAGS+= -I${.CURDIR}/../../ficl +CFLAGS+= -I${.CURDIR}/../../ficl/i386 +LIBFICL= ${.OBJDIR}/../../ficl/libficl.a +.endif + +# Include bcache code. +HAVE_BCACHE= yes + +# Always add MI sources +.PATH: ${.CURDIR}/../../common +.include "${.CURDIR}/../../common/Makefile.inc" +CFLAGS+= -I${.CURDIR}/../../common + +FILES= loader.efi +FILESMODE_loader.efi= ${BINMODE} + +LDSCRIPT= ${.CURDIR}/ldscript.${MACHINE_ARCH} +LDFLAGS= -Wl,-T${LDSCRIPT} -shared -symbolic + +${PROG}: ${LDSCRIPT} + +CLEANFILES= vers.c loader.efi + +NEWVERSWHAT= "EFI loader" ${MACHINE_ARCH} + +vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version + sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} + +OBJCOPY?= objcopy +OBJDUMP?= objdump + +loader.efi: loader.sym + if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ + ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ + exit 1; \ + fi + ${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \ + -j .rel.dyn -j .reloc -j .sdata -j .text -j set_Xcommand_set \ + --target=efi-app-ia32 ${.ALLSRC} ${.TARGET} + +LIBEFI= ${.OBJDIR}/../../efi/libefi/libefi.a +CFLAGS+= -I${.CURDIR}/../libi386 +CFLAGS+= -I${.CURDIR}/../btx/lib + +DPADD= ${LIBFICL} ${LIBEFI} ${LIBSTAND} +LDADD= ${LIBFICL} ${LIBEFI} -lstand + +.include Added: head/sys/boot/i386/efi/autoload.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/autoload.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,9 @@ +#include +__FBSDID("$FreeBSD$"); + +int +i386_autoload(void) +{ + + return (0); +} Added: head/sys/boot/i386/efi/bootinfo.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/bootinfo.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,297 @@ +/*- + * Copyright (c) 1998 Michael Smith + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include "bootstrap.h" +#include "libi386.h" +#include + +/* + * Return a 'boothowto' value corresponding to the kernel arguments in + * (kargs) and any relevant environment variables. + */ +static struct +{ + const char *ev; + int mask; +} howto_names[] = { + { "boot_askname", RB_ASKNAME}, + { "boot_cdrom", RB_CDROM}, + { "boot_ddb", RB_KDB}, + { "boot_dfltroot", RB_DFLTROOT}, + { "boot_gdb", RB_GDB}, + { "boot_multicons", RB_MULTIPLE}, + { "boot_mute", RB_MUTE}, + { "boot_pause", RB_PAUSE}, + { "boot_serial", RB_SERIAL}, + { "boot_single", RB_SINGLE}, + { "boot_verbose", RB_VERBOSE}, + { NULL, 0} +}; + +static const char howto_switches[] = "aCdrgDmphsv"; +static int howto_masks[] = { + RB_ASKNAME, RB_CDROM, RB_KDB, RB_DFLTROOT, RB_GDB, RB_MULTIPLE, + RB_MUTE, RB_PAUSE, RB_SERIAL, RB_SINGLE, RB_VERBOSE +}; + +int +bi_getboothowto(char *kargs) +{ + const char *sw; + char *opts; + int howto, i; + + howto = 0; + + /* Get the boot options from the environment first. */ + for (i = 0; howto_names[i].ev != NULL; i++) { + if (getenv(howto_names[i].ev) != NULL) + howto |= howto_names[i].mask; + } + + /* Parse kargs */ + if (kargs == NULL) + return (howto); + + opts = strchr(kargs, '-'); + while (opts != NULL) { + while (*(++opts) != '\0') { + sw = strchr(howto_switches, *opts); + if (sw == NULL) + break; + howto |= howto_masks[sw - howto_switches]; + } + opts = strchr(opts, '-'); + } + + return (howto); +} + +/* + * Copy the environment into the load area starting at (addr). + * Each variable is formatted as =, with a single nul + * separating each variable, and a double nul terminating the environment. + */ +vm_offset_t +bi_copyenv(vm_offset_t start) +{ + struct env_var *ep; + vm_offset_t addr, last; + size_t len; + + addr = last = start; + + /* Traverse the environment. */ + for (ep = environ; ep != NULL; ep = ep->ev_next) { + len = strlen(ep->ev_name); + if (i386_copyin(ep->ev_name, addr, len) != len) + break; + addr += len; + if (i386_copyin("=", addr, 1) != 1) + break; + addr++; + if (ep->ev_value != NULL) { + len = strlen(ep->ev_value); + if (i386_copyin(ep->ev_value, addr, len) != len) + break; + addr += len; + } + if (i386_copyin("", addr, 1) != 1) + break; + last = ++addr; + } + + if (i386_copyin("", last++, 1) != 1) + last = start; + return(last); +} + +/* + * Copy module-related data into the load area, where it can be + * used as a directory for loaded modules. + * + * Module data is presented in a self-describing format. Each datum + * is preceded by a 32-bit identifier and a 32-bit size field. + * + * Currently, the following data are saved: + * + * MOD_NAME (variable) module name (string) + * MOD_TYPE (variable) module type (string) + * MOD_ARGS (variable) module parameters (string) + * MOD_ADDR sizeof(vm_offset_t) module load address + * MOD_SIZE sizeof(size_t) module size + * MOD_METADATA (variable) type-specific metadata + */ +#define COPY32(v, a) { \ + u_int32_t x = (v); \ + i386_copyin(&x, a, sizeof(x)); \ + a += sizeof(x); \ +} + +#define MOD_STR(t, a, s) { \ + COPY32(t, a); \ + COPY32(strlen(s) + 1, a); \ + i386_copyin(s, a, strlen(s) + 1); \ + a += roundup(strlen(s) + 1, sizeof(u_int64_t));\ +} + +#define MOD_NAME(a, s) MOD_STR(MODINFO_NAME, a, s) +#define MOD_TYPE(a, s) MOD_STR(MODINFO_TYPE, a, s) +#define MOD_ARGS(a, s) MOD_STR(MODINFO_ARGS, a, s) + +#define MOD_VAR(t, a, s) { \ + COPY32(t, a); \ + COPY32(sizeof(s), a); \ + i386_copyin(&s, a, sizeof(s)); \ + a += roundup(sizeof(s), sizeof(u_int64_t)); \ +} + +#define MOD_ADDR(a, s) MOD_VAR(MODINFO_ADDR, a, s) +#define MOD_SIZE(a, s) MOD_VAR(MODINFO_SIZE, a, s) + +#define MOD_METADATA(a, mm) { \ + COPY32(MODINFO_METADATA | mm->md_type, a); \ + COPY32(mm->md_size, a); \ + i386_copyin(mm->md_data, a, mm->md_size); \ + a += roundup(mm->md_size, sizeof(u_int64_t));\ +} + +#define MOD_END(a) { \ + COPY32(MODINFO_END, a); \ + COPY32(0, a); \ +} + +vm_offset_t +bi_copymodules(vm_offset_t addr) +{ + struct preloaded_file *fp; + struct file_metadata *md; + + /* Start with the first module on the list, should be the kernel. */ + for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { + /* The name field must come first. */ + MOD_NAME(addr, fp->f_name); + MOD_TYPE(addr, fp->f_type); + if (fp->f_args) + MOD_ARGS(addr, fp->f_args); + MOD_ADDR(addr, fp->f_addr); + MOD_SIZE(addr, fp->f_size); + for (md = fp->f_metadata; md != NULL; md = md->md_next) { + if (!(md->md_type & MODINFOMD_NOCOPY)) + MOD_METADATA(addr, md); + } + } + MOD_END(addr); + return(addr); +} + +/* + * Load the information expected by the kernel. + * + * - The kernel environment is copied into kernel space. + * - Module metadata are formatted and placed in kernel space. + */ +int +bi_load(struct preloaded_file *fp, uint64_t *bi_addr) +{ + struct bootinfo bi; + struct preloaded_file *xp; + struct file_metadata *md; + struct devdesc *rootdev; + char *rootdevname; + vm_offset_t addr, ssym, esym; + + bzero(&bi, sizeof(struct bootinfo)); + bi.bi_version = 1; +// bi.bi_boothowto = bi_getboothowto(fp->f_args); + + /* + * Allow the environment variable 'rootdev' to override the supplied + * device. This should perhaps go to MI code and/or have $rootdev + * tested/set by MI code before launching the kernel. + */ + rootdevname = getenv("rootdev"); + i386_getdev((void**)&rootdev, rootdevname, NULL); + if (rootdev != NULL) { + /* Try reading /etc/fstab to select the root device. */ + getrootmount(i386_fmtdev(rootdev)); + free(rootdev); + } + + md = file_findmetadata(fp, MODINFOMD_SSYM); + ssym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; + md = file_findmetadata(fp, MODINFOMD_ESYM); + esym = (md != NULL) ? *((vm_offset_t *)&(md->md_data)) : 0; + if (ssym != 0 && esym != 0) { + bi.bi_symtab = ssym; + bi.bi_esymtab = esym; + } + + /* Find the last module in the chain. */ + addr = 0; + for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { + if (addr < (xp->f_addr + xp->f_size)) + addr = xp->f_addr + xp->f_size; + } + + addr = (addr + 15) & ~15; + + /* Copy module list and metadata. */ + bi.bi_modulep = addr; + addr = bi_copymodules(addr); + if (addr <= bi.bi_modulep) { + addr = bi.bi_modulep; + bi.bi_modulep = 0; + } + + addr = (addr + 15) & ~15; + + /* Copy our environment. */ + bi.bi_envp = addr; + addr = bi_copyenv(addr); + if (addr <= bi.bi_envp) { + addr = bi.bi_envp; + bi.bi_envp = 0; + } + + addr = (addr + PAGE_MASK) & ~PAGE_MASK; + bi.bi_kernend = addr; + + return (ldr_bootinfo(&bi, bi_addr)); +} Added: head/sys/boot/i386/efi/conf.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/conf.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +struct devsw *devsw[] = { + &efipart_dev, + &efinet_dev, + NULL +}; + +struct fs_ops *file_system[] = { + &dosfs_fsops, + &ufs_fsops, + &cd9660_fsops, + &nfs_fsops, + &gzipfs_fsops, + NULL +}; + +struct netif_driver *netif_drivers[] = { + &efinetif, + NULL +}; + +#ifdef notyet +extern struct file_format amd64_elf; +extern struct file_format amd64_elf_obj; +#endif +extern struct file_format i386_elf; +extern struct file_format i386_elf_obj; + +struct file_format *file_formats[] = { +#ifdef notyet + &amd64_elf, + &amd64_elf_obj, +#endif + &i386_elf, + &i386_elf_obj, + NULL +}; + +extern struct console efi_console; + +struct console *consoles[] = { + &efi_console, + NULL +}; Added: head/sys/boot/i386/efi/devicename.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/devicename.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 1998 Michael Smith + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include "bootstrap.h" + +#include +#include + +static int i386_parsedev(struct devdesc **, const char *, const char **); + +/* + * Point (dev) at an allocated device specifier for the device matching the + * path in (devspec). If it contains an explicit device specification, + * use that. If not, use the default device. + */ +int +i386_getdev(void **vdev, const char *devspec, const char **path) +{ + struct devdesc **dev = (struct devdesc **)vdev; + int rv; + + /* + * If it looks like this is just a path and no device, then + * use the current device instead. + */ + if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { + rv = i386_parsedev(dev, getenv("currdev"), NULL); + if (rv == 0 && path != NULL) + *path = devspec; + return (rv); + } + + /* Parse the device name off the beginning of the devspec. */ + return (i386_parsedev(dev, devspec, path)); +} + +/* + * Point (dev) at an allocated device specifier matching the string version + * at the beginning of (devspec). Return a pointer to the remaining + * text in (path). + * + * In all cases, the beginning of (devspec) is compared to the names + * of known devices in the device switch, and then any following text + * is parsed according to the rules applied to the device type. + * + * For disk-type devices, the syntax is: + * + * fs: + */ +static int +i386_parsedev(struct devdesc **dev, const char *devspec, const char **path) +{ + struct devdesc *idev; + struct devsw *dv; + char *cp; + const char *np; + int i, err; + + /* minimum length check */ + if (strlen(devspec) < 2) + return (EINVAL); + + /* look for a device that matches */ + for (i = 0; devsw[i] != NULL; i++) { + dv = devsw[i]; + if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) + break; + } + if (devsw[i] == NULL) + return (ENOENT); + + idev = malloc(sizeof(struct devdesc)); + if (idev == NULL) + return (ENOMEM); + + idev->d_dev = dv; + idev->d_type = dv->dv_type; + idev->d_unit = -1; + + err = 0; + np = devspec + strlen(dv->dv_name); + if (*np != '\0' && *np != ':') { + idev->d_unit = strtol(np, &cp, 0); + if (cp == np) { + idev->d_unit = -1; + free(idev); + return (EUNIT); + } + } + if (*cp != '\0' && *cp != ':') { + free(idev); + return (EINVAL); + } + + if (path != NULL) + *path = (*cp == 0) ? cp : cp + 1; + if (dev != NULL) + *dev = idev; + else + free(idev); + return (0); +} + +char * +i386_fmtdev(void *vdev) +{ + struct devdesc *dev = (struct devdesc *)vdev; + static char buf[32]; /* XXX device length constant? */ + + switch(dev->d_type) { + case DEVT_NONE: + strcpy(buf, "(no device)"); + break; + + default: + sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit); + break; + } + + return(buf); +} + +/* + * Set currdev to suit the value being supplied in (value) + */ +int +i386_setcurrdev(struct env_var *ev, int flags, const void *value) +{ + struct devdesc *ncurr; + int rv; + + rv = i386_parsedev(&ncurr, value, NULL); + if (rv != 0) + return(rv); + + free(ncurr); + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); + return (0); +} Added: head/sys/boot/i386/efi/efimd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/efimd.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 2004, 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include + +#include +#include + +#define EFI_INTEL_FPSWA \ + {0xc41b6531,0x97b9,0x11d3,{0x9a,0x29,0x00,0x90,0x27,0x3f,0xc1,0x4d}} + +static EFI_GUID fpswa_guid = EFI_INTEL_FPSWA; + +/* DIG64 Headless Console & Debug Port Table. */ +#define HCDP_TABLE_GUID \ + {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}} + +static EFI_GUID hcdp_guid = HCDP_TABLE_GUID; + +static UINTN mapkey; + +uint64_t +ldr_alloc(vm_offset_t va) +{ + + return (0); +} + +int +ldr_bootinfo(struct bootinfo *bi, uint64_t *bi_addr) +{ + VOID *fpswa; + EFI_MEMORY_DESCRIPTOR *mm; + EFI_PHYSICAL_ADDRESS addr; + EFI_HANDLE handle; + EFI_STATUS status; + size_t bisz; + UINTN mmsz, pages, sz; + UINT32 mmver; + + bi->bi_systab = (uint64_t)ST; + bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp_guid); + + sz = sizeof(EFI_HANDLE); + status = BS->LocateHandle(ByProtocol, &fpswa_guid, 0, &sz, &handle); + if (status == 0) + status = BS->HandleProtocol(handle, &fpswa_guid, &fpswa); + bi->bi_fpswa = (status == 0) ? (uint64_t)fpswa : 0; + + bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; + + /* + * Allocate enough pages to hold the bootinfo block and the memory + * map EFI will return to us. The memory map has an unknown size, + * so we have to determine that first. Note that the AllocatePages + * call can itself modify the memory map, so we have to take that + * into account as well. The changes to the memory map are caused + * by splitting a range of free memory into two (AFAICT), so that + * one is marked as being loader data. + */ + sz = 0; + BS->GetMemoryMap(&sz, NULL, &mapkey, &mmsz, &mmver); + sz += mmsz; + sz = (sz + 15) & ~15; + pages = EFI_SIZE_TO_PAGES(sz + bisz); + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, + &addr); + if (EFI_ERROR(status)) { + printf("%s: AllocatePages() returned 0x%lx\n", __func__, + (long)status); + return (ENOMEM); + } + + /* + * Read the memory map and stash it after bootinfo. Align the + * memory map on a 16-byte boundary (the bootinfo block is page + * aligned). + */ + *bi_addr = addr; + mm = (void *)(addr + bisz); + sz = (EFI_PAGE_SIZE * pages) - bisz; + status = BS->GetMemoryMap(&sz, mm, &mapkey, &mmsz, &mmver); + if (EFI_ERROR(status)) { + printf("%s: GetMemoryMap() returned 0x%lx\n", __func__, + (long)status); + return (EINVAL); + } + bi->bi_memmap = (uint64_t)mm; + bi->bi_memmap_size = sz; + bi->bi_memdesc_size = mmsz; + bi->bi_memdesc_version = mmver; + + bcopy(bi, (void *)(*bi_addr), sizeof(*bi)); + return (0); +} + +int +ldr_enter(const char *kernel) +{ + EFI_STATUS status; + + status = BS->ExitBootServices(IH, mapkey); + if (EFI_ERROR(status)) { + printf("%s: ExitBootServices() returned 0x%lx\n", __func__, + (long)status); + return (EINVAL); + } + + return (0); +} Added: head/sys/boot/i386/efi/elf32_freebsd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/elf32_freebsd.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 1998 Michael Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include "bootstrap.h" +#include "../libi386/libi386.h" +#include "../btx/lib/btxv86.h" + +extern void __exec(caddr_t addr, ...); + + +static int elf32_exec(struct preloaded_file *amp); +static int elf32_obj_exec(struct preloaded_file *amp); + +struct file_format i386_elf = { elf32_loadfile, elf32_exec }; +struct file_format i386_elf_obj = { elf32_obj_loadfile, elf32_obj_exec }; + +/* + * There is an ELF kernel and one or more ELF modules loaded. + * We wish to start executing the kernel image, so make such + * preparations as are required, and do so. + */ +static int +elf32_exec(struct preloaded_file *fp) +{ + struct file_metadata *md; + Elf_Ehdr *ehdr; + vm_offset_t entry, bootinfop, modulep, kernend; + int boothowto, err, bootdev; + + if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) + return(EFTYPE); + ehdr = (Elf_Ehdr *)&(md->md_data); + + err = bi_load(fp->f_args, &boothowto, &bootdev, &bootinfop, &modulep, &kernend); + if (err != 0) + return(err); + entry = ehdr->e_entry & 0xffffff; + + printf("Start @ 0x%lx ...\n", entry); + + ldr_enter(fp->f_name); + + dev_cleanup(); + __exec((void *)entry, boothowto, bootdev, 0, 0, 0, bootinfop, modulep, kernend); + + panic("exec returned"); +} + +static int +elf32_obj_exec(struct preloaded_file *fp) +{ + return (EFTYPE); +} Added: head/sys/boot/i386/efi/exec.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/exec.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2010 Rui Paulo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include "../btx/lib/btxv86.h" + +#include "../../common/bootstrap.h" + +uint32_t __base; +struct __v86 __v86; + +void +__v86int() +{ + printf("%s\n", __func__); + exit(1); +} + +void +__exec(caddr_t addr, ...) +{ + /* XXX this is wrong */ + __asm __volatile("movl %cr0, %eax"); + __asm __volatile("andl $0x7fffffff, %eax"); + __asm __volatile("mov %eax, %cr0"); + __asm __volatile("xorl %eax, %eax"); + __asm __volatile("mov %eax, %cr3"); + __asm __volatile("movl %cr0, %eax"); + __asm __volatile("andl $0xfffffffe, %eax"); + __asm __volatile("movl %eax, %cr0"); + __asm __volatile("jmp %0" :: "r" (addr)); +} Added: head/sys/boot/i386/efi/i386_copy.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/i386_copy.c Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 1998 Michael Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * MD primitives supporting placement of module data + * + * XXX should check load address/size against memory top. + */ +#include + +#include "libi386.h" +#include "btxv86.h" + +ssize_t +i386_copyin(const void *src, vm_offset_t dest, const size_t len) +{ + bcopy(src, PTOV(dest), len); + return(len); +} + +ssize_t +i386_copyout(const vm_offset_t src, void *dest, const size_t len) +{ + bcopy(PTOV(src), dest, len); + return(len); +} + + +ssize_t +i386_readin(const int fd, vm_offset_t dest, const size_t len) +{ + return (read(fd, PTOV(dest), len)); +} Added: head/sys/boot/i386/efi/ldscript.amd64 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/i386/efi/ldscript.amd64 Wed Apr 7 18:16:05 2010 (r206376) @@ -0,0 +1,75 @@ +/* $FreeBSD$ */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***