diff options
Diffstat (limited to 'sys')
39 files changed, 1269 insertions, 2798 deletions
diff --git a/sys/boot/Makefile b/sys/boot/Makefile index bf76176..8d8ffed 100644 --- a/sys/boot/Makefile +++ b/sys/boot/Makefile @@ -8,7 +8,7 @@ SUBDIR+= ficl .endif # Build EFI library. -.if ${MACHINE_ARCH} == "ia64" +.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "ia64" SUBDIR+= efi .endif diff --git a/sys/boot/efi/include/efilib.h b/sys/boot/efi/include/efilib.h index acb1c31..220e01a 100644 --- a/sys/boot/efi/include/efilib.h +++ b/sys/boot/efi/include/efilib.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2000 Doug Rabson + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,24 +24,31 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD$ */ -#include <efifpswa.h> +#include <stand.h> extern EFI_HANDLE IH; extern EFI_SYSTEM_TABLE *ST; extern EFI_BOOT_SERVICES *BS; extern EFI_RUNTIME_SERVICES *RS; -/* DIG64 Headless Console & Debug Port Table. */ -#define HCDP_TABLE_GUID \ - {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}} +extern struct devsw efifs_dev; +extern struct fs_ops efifs_fsops; + +extern struct devsw efinet_dev; +extern struct netif_driver efinetif; void *efi_get_table(EFI_GUID *tbl); void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); -EFI_PHYSICAL_ADDRESS efimd_va2pa(EFI_VIRTUAL_ADDRESS); +int efi_register_handles(struct devsw *, EFI_HANDLE *, int); +EFI_HANDLE efi_find_handle(struct devsw *, int); +int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *); + +int efi_status_to_errno(EFI_STATUS); +time_t efi_time(EFI_TIME *); EFI_STATUS main(int argc, CHAR16 *argv[]); void exit(EFI_STATUS status); diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile index c52ffc9..5c504a3 100644 --- a/sys/boot/efi/libefi/Makefile +++ b/sys/boot/efi/libefi/Makefile @@ -1,27 +1,16 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../../${MACHINE_ARCH}/${MACHINE_ARCH} - LIB= efi INTERNALLIB= -SRCS= bootinfo.c copy.c delay.c devicename.c efi_console.c efifs.c efinet.c \ - elf_freebsd.c libefi.c module.c time.c - -.if ${MACHINE_ARCH} == "ia64" -SRCS+= efifpswa.c pal.S -.endif +SRCS= delay.c efi_console.c efifs.c efinet.c errno.c handles.c libefi.c \ + time.c CFLAGS+= -I${.CURDIR}/../include -CFLAGS+= -I${.CURDIR}/../include/${MACHINE_ARCH} +CFLAGS+= -I${.CURDIR}/../include/${MACHINE_ARCH:S/amd64/i386/} CFLAGS+= -I${.CURDIR}/../../../../lib/libstand # Pick up the bootstrap header for some interface items CFLAGS+= -I${.CURDIR}/../../common -# Make the disk code more talkative -.if defined(BOOT_DISK_DEBUG) -CFLAGS+= -DDISK_DEBUG -.endif - .include <bsd.lib.mk> diff --git a/sys/boot/efi/libefi/bootinfo.c b/sys/boot/efi/libefi/bootinfo.c deleted file mode 100644 index bfda81d..0000000 --- a/sys/boot/efi/libefi/bootinfo.c +++ /dev/null @@ -1,351 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> -#include <sys/param.h> -#include <sys/reboot.h> -#include <sys/linker.h> -#include <machine/elf.h> -#include <machine/bootinfo.h> - -#include <efi.h> -#include <efilib.h> - -#include "bootstrap.h" - -static EFI_GUID hcdp = HCDP_TABLE_GUID; - -/* - * 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} -}; - -extern char *efi_fmtdev(void *vdev); - -int -bi_getboothowto(char *kargs) -{ - char *cp; - int howto; - int active; - int i; - - /* Parse kargs */ - howto = 0; - if (kargs != NULL) { - cp = kargs; - active = 0; - while (*cp != 0) { - if (!active && (*cp == '-')) { - active = 1; - } else if (active) - switch (*cp) { - case 'a': - howto |= RB_ASKNAME; - break; - case 'C': - howto |= RB_CDROM; - break; - case 'd': - howto |= RB_KDB; - break; - case 'D': - howto |= RB_MULTIPLE; - break; - case 'm': - howto |= RB_MUTE; - break; - case 'g': - howto |= RB_GDB; - break; - case 'h': - howto |= RB_SERIAL; - break; - case 'p': - howto |= RB_PAUSE; - break; - case 'r': - howto |= RB_DFLTROOT; - break; - case 's': - howto |= RB_SINGLE; - break; - case 'v': - howto |= RB_VERBOSE; - break; - default: - active = 0; - break; - } - cp++; - } - } - /* get equivalents from the environment */ - for (i = 0; howto_names[i].ev != NULL; i++) - if (getenv(howto_names[i].ev) != NULL) - howto |= howto_names[i].mask; - if (!strcmp(getenv("console"), "comconsole")) - howto |= RB_SERIAL; - if (!strcmp(getenv("console"), "nullconsole")) - howto |= RB_MUTE; - return(howto); -} - -/* - * Copy the environment into the load area starting at (addr). - * Each variable is formatted as <name>=<value>, with a single nul - * separating each variable, and a double nul terminating the environment. - */ -vm_offset_t -bi_copyenv(vm_offset_t addr) -{ - struct env_var *ep; - - /* traverse the environment */ - for (ep = environ; ep != NULL; ep = ep->ev_next) { - efi_copyin(ep->ev_name, addr, strlen(ep->ev_name)); - addr += strlen(ep->ev_name); - efi_copyin("=", addr, 1); - addr++; - if (ep->ev_value != NULL) { - efi_copyin(ep->ev_value, addr, strlen(ep->ev_value)); - addr += strlen(ep->ev_value); - } - efi_copyin("", addr, 1); - addr++; - } - efi_copyin("", addr, 1); - addr++; - return(addr); -} - -/* - * 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); \ - efi_copyin(&x, a, sizeof(x)); \ - a += sizeof(x); \ -} - -#define MOD_STR(t, a, s) { \ - COPY32(t, a); \ - COPY32(strlen(s) + 1, a); \ - efi_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); \ - efi_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); \ - efi_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) { - - MOD_NAME(addr, fp->f_name); /* this field must come first */ - 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 bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey, - UINTN pages) -{ - char *rootdevname; - struct efi_devdesc *rootdev; - struct preloaded_file *xp; - vm_offset_t addr, bootinfo_addr; - vm_offset_t ssym, esym; - struct file_metadata *md; - EFI_STATUS status; - UINTN bisz, key; - - /* - * Version 1 bootinfo. - */ - bi->bi_magic = BOOTINFO_MAGIC; - bi->bi_version = 1; - - /* - * Calculate boothowto. - */ - bi->bi_boothowto = bi_getboothowto(fp->f_args); - - /* - * Stash EFI System Table. - */ - bi->bi_systab = (u_int64_t) ST; - - /* - * 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"); - efi_getdev((void **)(&rootdev), rootdevname, NULL); - if (rootdev == NULL) { /* bad $rootdev/$currdev */ - printf("can't determine root device\n"); - return(EINVAL); - } - - /* Try reading the /etc/fstab file to select the root device */ - getrootmount(efi_fmtdev((void *)rootdev)); - free(rootdev); - - ssym = esym = 0; - if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL) - ssym = *((vm_offset_t *)&(md->md_data)); - if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL) - esym = *((vm_offset_t *)&(md->md_data)); - if (ssym == 0 || esym == 0) - ssym = esym = 0; /* sanity */ - - bi->bi_symtab = ssym; - bi->bi_esymtab = esym; - - bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp); /* DIG64 HCDP table addr. */ - fpswa_init(&bi->bi_fpswa); /* find FPSWA interface */ - - /* 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; - } - - /* pad to a page boundary */ - addr = (addr + PAGE_MASK) & ~PAGE_MASK; - - /* copy our environment */ - bi->bi_envp = addr; - addr = bi_copyenv(addr); - - /* pad to a page boundary */ - addr = (addr + PAGE_MASK) & ~PAGE_MASK; - - /* copy module list and metadata */ - bi->bi_modulep = addr; - addr = bi_copymodules(addr); - - /* all done copying stuff in, save end of loaded object space */ - bi->bi_kernend = addr; - - /* - * Read the memory map and stash it after bootinfo. Align the memory map - * on a 16-byte boundary (the bootinfo block is page aligned). - */ - bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; - bi->bi_memmap = ((u_int64_t)bi) + bisz; - bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz; - status = BS->GetMemoryMap(&bi->bi_memmap_size, - (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key, - &bi->bi_memdesc_size, &bi->bi_memdesc_version); - if (EFI_ERROR(status)) { - printf("bi_load: Can't read memory map\n"); - return EINVAL; - } - *mapkey = key; - - return(0); -} diff --git a/sys/boot/efi/libefi/copy.c b/sys/boot/efi/libefi/copy.c deleted file mode 100644 index 4b4b9bd..0000000 --- a/sys/boot/efi/libefi/copy.c +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <efi.h> -#include <efilib.h> -#include <stand.h> - -int -efi_copyin(void *src, vm_offset_t va, size_t len) -{ - - bcopy(src, (void *)efimd_va2pa(va), len); - return (len); -} - -int -efi_copyout(vm_offset_t va, void *dst, size_t len) -{ - - bcopy((void *)efimd_va2pa(va), dst, len); - return (len); -} - -int -efi_readin(int fd, vm_offset_t va, size_t len) -{ - - return (read(fd, (void *)efimd_va2pa(va), len)); -} diff --git a/sys/boot/efi/libefi/devicename.c b/sys/boot/efi/libefi/devicename.c deleted file mode 100644 index 62c943a..0000000 --- a/sys/boot/efi/libefi/devicename.c +++ /dev/null @@ -1,241 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> -#include <sys/disklabel.h> -#include "bootstrap.h" - -#include <efi.h> -#include <efilib.h> -#include "efiboot.h" - -static int efi_parsedev(struct efi_devdesc **dev, const char *devspec, const char **path); - -/* - * 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 -efi_getdev(void **vdev, const char *devspec, const char **path) -{ - struct efi_devdesc **dev = (struct efi_devdesc **)vdev; - int rv; - - /* - * If it looks like this is just a path and no - * device, go with the current device. - */ - if ((devspec == NULL) || - (devspec[0] == '/') || - (strchr(devspec, ':') == NULL)) { - - if (((rv = efi_parsedev(dev, getenv("currdev"), NULL)) == 0) && - (path != NULL)) - *path = devspec; - return(rv); - } - - /* - * Try to parse the device name off the beginning of the devspec - */ - return(efi_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: - * - * disk<unit>[s<slice>][<partition>]: - * - */ -static int -efi_parsedev(struct efi_devdesc **dev, const char *devspec, const char **path) -{ - struct efi_devdesc *idev; - struct devsw *dv; - int i, unit, slice, partition, err; - char *cp; - const char *np; - - /* minimum length check */ - if (strlen(devspec) < 2) - return(EINVAL); - - /* look for a device that matches */ - for (i = 0, dv = NULL; devsw[i] != NULL; i++) { - if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { - dv = devsw[i]; - break; - } - } - - if (dv == NULL) - return(ENOENT); - idev = malloc(sizeof(struct efi_devdesc)); - err = 0; - np = (devspec + strlen(dv->dv_name)); - - switch(dv->dv_type) { - case DEVT_NONE: /* XXX what to do here? Do we care? */ - break; - - case DEVT_DISK: - unit = -1; - slice = -1; - partition = -1; - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 10); /* next comes the unit number */ - if (cp == np) { - err = EUNIT; - goto fail; - } - if (*cp == 's') { /* got a slice number */ - np = cp + 1; - slice = strtol(np, &cp, 10); - if (cp == np) { - err = ESLICE; - goto fail; - } - } - if (*cp && (*cp != ':')) { - partition = *cp - 'a'; /* get a partition number */ - if ((partition < 0) || (partition >= MAXPARTITIONS)) { - err = EPART; - goto fail; - } - cp++; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - - idev->d_unit = unit; - idev->d_kind.efidisk.slice = slice; - idev->d_kind.efidisk.partition = partition; - - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - case DEVT_NET: - unit = 0; - - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 0); /* get unit number if present */ - if (cp == np) { - err = EUNIT; - goto fail; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - - idev->d_unit = unit; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - default: - err = EINVAL; - goto fail; - } - idev->d_dev = dv; - idev->d_type = dv->dv_type; - if (dev == NULL) { - free(idev); - } else { - *dev = idev; - } - return(0); - - fail: - free(idev); - return(err); -} - - -char * -efi_fmtdev(void *vdev) -{ - struct efi_devdesc *dev = (struct efi_devdesc *)vdev; - static char buf[128]; /* XXX device length constant? */ - char *cp; - - switch(dev->d_type) { - case DEVT_NONE: - strcpy(buf, "(no device)"); - break; - - case DEVT_DISK: - cp = buf; - cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_unit); - if (dev->d_kind.efidisk.slice > 0) - cp += sprintf(cp, "s%d", dev->d_kind.efidisk.slice); - if (dev->d_kind.efidisk.partition >= 0) - cp += sprintf(cp, "%c", dev->d_kind.efidisk.partition + 'a'); - strcat(cp, ":"); - break; - - case DEVT_NET: - 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 -efi_setcurrdev(struct env_var *ev, int flags, void *value) -{ - struct efi_devdesc *ncurr; - int rv; - - if ((rv = efi_parsedev(&ncurr, value, NULL)) != 0) - return(rv); - free(ncurr); - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - return(0); -} - diff --git a/sys/boot/efi/libefi/efiboot.h b/sys/boot/efi/libefi/efiboot.h deleted file mode 100644 index 74e659a..0000000 --- a/sys/boot/efi/libefi/efiboot.h +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 1996 - * Matthias Drochner. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the NetBSD Project - * by Matthias Drochner. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * EFI fully-qualified device descriptor - */ -struct efi_devdesc { - struct devsw *d_dev; - int d_type; -#define DEVT_NONE 0 -#define DEVT_DISK 1 -#define DEVT_NET 2 - int d_unit; - EFI_HANDLE d_handle; - union { - struct { - int slice; - int partition; - } efidisk; - } d_kind; -}; - -extern int efi_getdev(void **vdev, const char *devspec, const char **path); -extern char *efi_fmtdev(void *vdev); -extern int efi_setcurrdev(struct env_var *ev, int flags, void *value); - -#define MAXDEV 31 /* maximum number of distinct devices */ - -typedef unsigned long physaddr_t; - -/* exported devices XXX rename? */ -extern struct devsw efifs_dev; -extern struct devsw efi_disk; -extern struct netif_driver efi_net; - -/* Find EFI network resources */ -extern void efinet_init_driver(void); - -/* Map handles to units */ -int efifs_get_unit(EFI_HANDLE); - -/* Wrapper over EFI filesystems. */ -extern struct fs_ops efi_fsops; - -/* this is in startup code */ -extern void delay(int); -extern void reboot(void); - -extern ssize_t efi_copyin(const void *src, vm_offset_t dest, size_t len); -extern ssize_t efi_copyout(const vm_offset_t src, void *dest, size_t len); -extern ssize_t efi_readin(int fd, vm_offset_t dest, size_t len); - -extern int efi_boot(void); -extern int efi_autoload(void); - -extern int fpswa_init(u_int64_t *fpswa_interface); - -struct bootinfo; -struct preloaded_file; -extern int bi_load(struct bootinfo *, struct preloaded_file *, - UINTN *mapkey, UINTN pages); diff --git a/sys/boot/efi/libefi/efifpswa.c b/sys/boot/efi/libefi/efifpswa.c deleted file mode 100644 index f7d5147..0000000 --- a/sys/boot/efi/libefi/efifpswa.c +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * Copyright (c) 2001 Peter Wemm <peter@FreeBSD.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/time.h> -#include <stddef.h> -#include <stand.h> -#include <stdarg.h> - -#include <efi.h> -#include <efilib.h> -#include "efiboot.h" - -int -fpswa_init(u_int64_t *fpswa_interface) -{ - EFI_STATUS status; - static EFI_GUID fpswaid = EFI_INTEL_FPSWA; - UINTN sz; - EFI_HANDLE fpswa_handle; - FPSWA_INTERFACE *fpswa; - - *fpswa_interface = 0; - sz = sizeof(EFI_HANDLE); - status = BS->LocateHandle(ByProtocol, &fpswaid, 0, &sz, &fpswa_handle); - if (EFI_ERROR(status)) - return ENOENT; - - status = BS->HandleProtocol(fpswa_handle, &fpswaid, (VOID **)&fpswa); - if (EFI_ERROR(status)) - return ENOENT; - *fpswa_interface = (u_int64_t)fpswa; - return 0; -} diff --git a/sys/boot/efi/libefi/efifs.c b/sys/boot/efi/libefi/efifs.c index ce20a6e..716102c 100644 --- a/sys/boot/efi/libefi/efifs.c +++ b/sys/boot/efi/libefi/efifs.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2001 Doug Rabson + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,88 +23,100 @@ * 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. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include <sys/param.h> #include <sys/time.h> #include <stddef.h> -#include <stand.h> #include <stdarg.h> +#include <bootstrap.h> + #include <efi.h> #include <efilib.h> -#include "efiboot.h" +#include <efiprot.h> /* Perform I/O in blocks of size EFI_BLOCK_SIZE. */ #define EFI_BLOCK_SIZE (1024 * 1024) +union fileinfo { + EFI_FILE_INFO info; + char bytes[sizeof(EFI_FILE_INFO) + 508]; +}; + +static EFI_GUID sfs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; +static EFI_GUID fs_guid = EFI_FILE_SYSTEM_INFO_ID; +static EFI_GUID fi_guid = EFI_FILE_INFO_ID; + static int efifs_open(const char *upath, struct open_file *f) { - struct efi_devdesc *dev = f->f_devdata; - static EFI_GUID sfsid = SIMPLE_FILE_SYSTEM_PROTOCOL; - EFI_FILE_IO_INTERFACE *sfs; - EFI_FILE *root; - EFI_FILE *file; + struct devdesc *dev = f->f_devdata; + EFI_FILE_IO_INTERFACE *fsif; + EFI_FILE *file, *root; + EFI_HANDLE h; EFI_STATUS status; - CHAR16 *cp; - CHAR16 *path; - - /* - * We cannot blindly assume that f->f_devdata points to a - * efi_devdesc structure. Before we dereference 'dev', make - * sure that the underlying device is ours. - */ - if (f->f_dev != &efifs_dev || dev->d_handle == NULL) - return ENOENT; - - status = BS->HandleProtocol(dev->d_handle, &sfsid, (VOID **)&sfs); + CHAR16 *cp, *path; + + if (f->f_dev != &efifs_dev || dev->d_unit < 0) + return (EINVAL); + + h = efi_find_handle(f->f_dev, dev->d_unit); + if (h == NULL) + return (EINVAL); + + status = BS->HandleProtocol(h, &sfs_guid, (VOID **)&fsif); if (EFI_ERROR(status)) - return ENOENT; + return (efi_status_to_errno(status)); - /* - * Find the root directory. - */ - status = sfs->OpenVolume(sfs, &root); + /* Get the root directory. */ + status = fsif->OpenVolume(fsif, &root); + if (EFI_ERROR(status)) + return (efi_status_to_errno(status)); - /* - * Convert path to CHAR16, skipping leading separators. - */ while (*upath == '/') upath++; - if (!*upath) { - /* Opening the root directory, */ + + /* Special case: opening the root directory. */ + if (*upath == '\0') { f->f_fsdata = root; - return 0; + return (0); + } + + path = malloc((strlen(upath) + 1) * sizeof(CHAR16)); + if (path == NULL) { + root->Close(root); + return (ENOMEM); } - cp = path = malloc((strlen(upath) + 1) * sizeof(CHAR16)); - if (path == NULL) - return ENOMEM; - while (*upath) { - if (*upath == '/') + + cp = path; + while (*upath != '\0') { + if (*upath == '/') { *cp = '\\'; - else + while (upath[1] == '/') + upath++; + } else *cp = *upath; upath++; cp++; } - *cp++ = 0; + *cp = 0; - /* - * Try to open it. - */ - status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0); + /* Open the file. */ + status = root->Open(root, &file, path, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); + if (status == EFI_ACCESS_DENIED || status == EFI_WRITE_PROTECTED) + status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0); free(path); - if (EFI_ERROR(status)) { - root->Close(root); - return ENOENT; - } - root->Close(root); + if (EFI_ERROR(status)) + return (efi_status_to_errno(status)); + f->f_fsdata = file; - return 0; + return (0); } static int @@ -111,8 +124,12 @@ efifs_close(struct open_file *f) { EFI_FILE *file = f->f_fsdata; + if (file == NULL) + return (EBADF); + file->Close(file); - return 0; + f->f_fsdata = NULL; + return (0); } static int @@ -123,15 +140,17 @@ efifs_read(struct open_file *f, void *buf, size_t size, size_t *resid) UINTN sz = size; char *bufp; + if (file == NULL) + return (EBADF); + bufp = buf; while (size > 0) { sz = size; if (sz > EFI_BLOCK_SIZE) sz = EFI_BLOCK_SIZE; status = file->Read(file, &sz, bufp); - twiddle(); if (EFI_ERROR(status)) - return EIO; + return (efi_status_to_errno(status)); if (sz == 0) break; size -= sz; @@ -139,7 +158,7 @@ efifs_read(struct open_file *f, void *buf, size_t size, size_t *resid) } if (resid) *resid = size; - return 0; + return (0); } static int @@ -150,15 +169,17 @@ efifs_write(struct open_file *f, void *buf, size_t size, size_t *resid) UINTN sz = size; char *bufp; + if (file == NULL) + return (EBADF); + bufp = buf; while (size > 0) { sz = size; if (sz > EFI_BLOCK_SIZE) sz = EFI_BLOCK_SIZE; status = file->Write(file, &sz, bufp); - twiddle(); if (EFI_ERROR(status)) - return EIO; + return (efi_status_to_errno(status)); if (sz == 0) break; size -= sz; @@ -166,7 +187,7 @@ efifs_write(struct open_file *f, void *buf, size_t size, size_t *resid) } if (resid) *resid = size; - return 0; + return (0); } static off_t @@ -175,156 +196,139 @@ efifs_seek(struct open_file *f, off_t offset, int where) EFI_FILE *file = f->f_fsdata; EFI_STATUS status; UINT64 base; - UINTN sz; - static EFI_GUID infoid = EFI_FILE_INFO_ID; - EFI_FILE_INFO info; + + if (file == NULL) + return (EBADF); switch (where) { case SEEK_SET: - base = 0; break; + case SEEK_END: + status = file->SetPosition(file, ~0ULL); + if (EFI_ERROR(status)) + return (-1); + /* FALLTHROUGH */ + case SEEK_CUR: status = file->GetPosition(file, &base); if (EFI_ERROR(status)) - return -1; + return (-1); + offset = (off_t)(base + offset); break; - case SEEK_END: - sz = sizeof(info); - status = file->GetInfo(file, &infoid, &sz, &info); - if (EFI_ERROR(status)) - return -1; - base = info.FileSize; - break; + default: + return (-1); } + if (offset < 0) + return (-1); - status = file->SetPosition(file, base + offset); - if (EFI_ERROR(status)) - return -1; - file->GetPosition(file, &base); - - return base; + status = file->SetPosition(file, (UINT64)offset); + return (EFI_ERROR(status) ? -1 : offset); } static int efifs_stat(struct open_file *f, struct stat *sb) { EFI_FILE *file = f->f_fsdata; + union fileinfo fi; EFI_STATUS status; - char *buf; UINTN sz; - static EFI_GUID infoid = EFI_FILE_INFO_ID; - EFI_FILE_INFO *info; - bzero(sb, sizeof(*sb)); + if (file == NULL) + return (EBADF); - buf = malloc(1024); - sz = 1024; - - status = file->GetInfo(file, &infoid, &sz, buf); - if (EFI_ERROR(status)) { - free(buf); - return -1; - } + bzero(sb, sizeof(*sb)); - info = (EFI_FILE_INFO *) buf; + sz = sizeof(fi); + status = file->GetInfo(file, &fi_guid, &sz, &fi); + if (EFI_ERROR(status)) + return (efi_status_to_errno(status)); - if (info->Attribute & EFI_FILE_READ_ONLY) - sb->st_mode = S_IRUSR; - else - sb->st_mode = S_IRUSR | S_IWUSR; - if (info->Attribute & EFI_FILE_DIRECTORY) + sb->st_mode = S_IRUSR | S_IRGRP | S_IROTH; + if ((fi.info.Attribute & EFI_FILE_READ_ONLY) == 0) + sb->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if (fi.info.Attribute & EFI_FILE_DIRECTORY) sb->st_mode |= S_IFDIR; else sb->st_mode |= S_IFREG; - sb->st_size = info->FileSize; - - free(buf); - return 0; + sb->st_nlink = 1; + sb->st_atime = efi_time(&fi.info.LastAccessTime); + sb->st_mtime = efi_time(&fi.info.ModificationTime); + sb->st_ctime = efi_time(&fi.info.CreateTime); + sb->st_size = fi.info.FileSize; + sb->st_blocks = fi.info.PhysicalSize / S_BLKSIZE; + sb->st_blksize = S_BLKSIZE; + sb->st_birthtime = sb->st_ctime; + return (0); } static int efifs_readdir(struct open_file *f, struct dirent *d) { EFI_FILE *file = f->f_fsdata; + union fileinfo fi; EFI_STATUS status; - char *buf; UINTN sz; - EFI_FILE_INFO *info; int i; - buf = malloc(1024); - sz = 1024; - - status = file->Read(file, &sz, buf); - if (EFI_ERROR(status) || sz < offsetof(EFI_FILE_INFO, FileName)) - return ENOENT; + if (file == NULL) + return (EBADF); - info = (EFI_FILE_INFO *) buf; + sz = sizeof(fi); + status = file->Read(file, &sz, &fi); + if (EFI_ERROR(status)) + return (efi_status_to_errno(status)); + if (sz == 0) + return (ENOENT); d->d_fileno = 0; d->d_reclen = sizeof(*d); - if (info->Attribute & EFI_FILE_DIRECTORY) + if (fi.info.Attribute & EFI_FILE_DIRECTORY) d->d_type = DT_DIR; else d->d_type = DT_REG; - d->d_namlen = ((info->Size - offsetof(EFI_FILE_INFO, FileName)) - / sizeof(CHAR16)); - for (i = 0; i < d->d_namlen; i++) - d->d_name[i] = info->FileName[i]; + for (i = 0; fi.info.FileName[i] != 0; i++) + d->d_name[i] = fi.info.FileName[i]; d->d_name[i] = 0; - - free(buf); - return 0; + d->d_namlen = i; + return (0); } -struct fs_ops efi_fsops = { - "fs", - efifs_open, - efifs_close, - efifs_read, - efifs_write, - efifs_seek, - efifs_stat, - efifs_readdir +struct fs_ops efifs_fsops = { + .fs_name = "efifs", + .fo_open = efifs_open, + .fo_close = efifs_close, + .fo_read = efifs_read, + .fo_write = efifs_write, + .fo_seek = efifs_seek, + .fo_stat = efifs_stat, + .fo_readdir = efifs_readdir }; -static EFI_HANDLE *fs_handles; -UINTN fs_handle_count; - -int -efifs_get_unit(EFI_HANDLE h) -{ - UINTN u; - - u = 0; - while (u < fs_handle_count && fs_handles[u] != h) - u++; - return ((u < fs_handle_count) ? u : -1); -} - static int efifs_dev_init(void) { - EFI_STATUS status; - UINTN sz; - static EFI_GUID sfsid = SIMPLE_FILE_SYSTEM_PROTOCOL; + EFI_HANDLE *handles; + EFI_STATUS status; + UINTN sz; + int err; sz = 0; - status = BS->LocateHandle(ByProtocol, &sfsid, 0, &sz, 0); - if (status != EFI_BUFFER_TOO_SMALL) - return ENOENT; - fs_handles = (EFI_HANDLE *) malloc(sz); - status = BS->LocateHandle(ByProtocol, &sfsid, 0, - &sz, fs_handles); - if (EFI_ERROR(status)) { - free(fs_handles); - return ENOENT; + status = BS->LocateHandle(ByProtocol, &sfs_guid, 0, &sz, 0); + if (status == EFI_BUFFER_TOO_SMALL) { + handles = (EFI_HANDLE *)malloc(sz); + status = BS->LocateHandle(ByProtocol, &sfs_guid, 0, &sz, + handles); + if (EFI_ERROR(status)) + free(handles); } - fs_handle_count = sz / sizeof(EFI_HANDLE); - - return 0; + if (EFI_ERROR(status)) + return (efi_status_to_errno(status)); + err = efi_register_handles(&efifs_dev, handles, + sz / sizeof(EFI_HANDLE)); + free(handles); + return (err); } /* @@ -333,14 +337,55 @@ efifs_dev_init(void) static void efifs_dev_print(int verbose) { - int i; - char line[80]; + union { + EFI_FILE_SYSTEM_INFO info; + char buffer[1024]; + } fi; + char line[80]; + EFI_FILE_IO_INTERFACE *fsif; + EFI_FILE *volume; + EFI_HANDLE h; + EFI_STATUS status; + UINTN sz; + int i, unit; - for (i = 0; i < fs_handle_count; i++) { - sprintf(line, " fs%d: EFI filesystem", i); + for (unit = 0, h = efi_find_handle(&efifs_dev, 0); + h != NULL; h = efi_find_handle(&efifs_dev, ++unit)) { + sprintf(line, " %s%d: ", efifs_dev.dv_name, unit); pager_output(line); - /* XXX more detail? */ + + status = BS->HandleProtocol(h, &sfs_guid, (VOID **)&fsif); + if (EFI_ERROR(status)) + goto err; + + status = fsif->OpenVolume(fsif, &volume); + if (EFI_ERROR(status)) + goto err; + + sz = sizeof(fi); + status = volume->GetInfo(volume, &fs_guid, &sz, &fi); + volume->Close(volume); + if (EFI_ERROR(status)) + goto err; + + if (fi.info.ReadOnly) + pager_output("[RO] "); + else + pager_output(" "); + for (i = 0; fi.info.VolumeLabel[i] != 0; i++) + fi.buffer[i] = fi.info.VolumeLabel[i]; + fi.buffer[i] = 0; + if (fi.buffer[0] != 0) + pager_output(fi.buffer); + else + pager_output("EFI filesystem"); pager_output("\n"); + continue; + + err: + sprintf(line, "[--] error %d: unable to obtain information\n", + efi_status_to_errno(status)); + pager_output(line); } } @@ -357,45 +402,40 @@ efifs_dev_print(int verbose) static int efifs_dev_open(struct open_file *f, ...) { - va_list args; - struct efi_devdesc *dev; - int unit; + va_list args; + struct devdesc *dev; va_start(args, f); - dev = va_arg(args, struct efi_devdesc*); + dev = va_arg(args, struct devdesc*); va_end(args); - unit = dev->d_unit; - if (unit < 0 || unit >= fs_handle_count) { - printf("attempt to open nonexistent EFI filesystem\n"); + if (dev->d_unit < 0) return(ENXIO); - } - - dev->d_handle = fs_handles[unit]; - - return 0; + return (0); } static int efifs_dev_close(struct open_file *f) { - return 0; + return (0); } static int efifs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { - return 0; + + return (ENOSYS); } struct devsw efifs_dev = { - "fs", - DEVT_DISK, - efifs_dev_init, - efifs_dev_strategy, - efifs_dev_open, - efifs_dev_close, - noioctl, - efifs_dev_print + .dv_name = "fs", + .dv_type = DEVT_DISK, + .dv_init = efifs_dev_init, + .dv_strategy = efifs_dev_strategy, + .dv_open = efifs_dev_open, + .dv_close = efifs_dev_close, + .dv_ioctl = noioctl, + .dv_print = efifs_dev_print, + .dv_cleanup = NULL }; diff --git a/sys/boot/efi/libefi/efinet.c b/sys/boot/efi/libefi/efinet.c index c6fc523..1eea860 100644 --- a/sys/boot/efi/libefi/efinet.c +++ b/sys/boot/efi/libefi/efinet.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2001 Doug Rabson + * Copyright (c) 2002, 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,10 +36,31 @@ __FBSDID("$FreeBSD$"); #include <net.h> #include <netif.h> +#include <dev_net.c> + #include <efi.h> #include <efilib.h> -extern struct netif_driver efi_net; +static EFI_GUID sn_guid = EFI_SIMPLE_NETWORK_PROTOCOL; + +static void efinet_end(struct netif *); +static int efinet_get(struct iodesc *, void *, size_t, time_t); +static void efinet_init(struct iodesc *, void *); +static int efinet_match(struct netif *, void *); +static int efinet_probe(struct netif *, void *); +static int efinet_put(struct iodesc *, void *, size_t); + +struct netif_driver efinetif = { + .netif_bname = "efinet", + .netif_match = efinet_match, + .netif_probe = efinet_probe, + .netif_init = efinet_init, + .netif_get = efinet_get, + .netif_put = efinet_put, + .netif_end = efinet_end, + .netif_ifs = NULL, + .netif_nifs = 0 +}; #ifdef EFINET_DEBUG static void @@ -74,21 +96,21 @@ dump_mode(EFI_SIMPLE_NETWORK_MODE *mode) } #endif -int +static int efinet_match(struct netif *nif, void *machdep_hint) { return (1); } -int +static int efinet_probe(struct netif *nif, void *machdep_hint) { return (0); } -int +static int efinet_put(struct iodesc *desc, void *pkt, size_t len) { struct netif *nif = desc->io_netif; @@ -100,7 +122,7 @@ efinet_put(struct iodesc *desc, void *pkt, size_t len) status = net->Transmit(net, 0, len, pkt, 0, 0, 0); if (status != EFI_SUCCESS) - return -1; + return (-1); /* Wait for the buffer to be transmitted */ do { @@ -113,11 +135,10 @@ efinet_put(struct iodesc *desc, void *pkt, size_t len) } while (status == EFI_SUCCESS && buf == 0); /* XXX How do we deal with status != EFI_SUCCESS now? */ - return (status == EFI_SUCCESS) ? len : -1; + return ((status == EFI_SUCCESS) ? len : -1); } - -int +static int efinet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) { struct netif *nif = desc->io_netif; @@ -143,30 +164,37 @@ efinet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) if (bufsz > len) bufsz = len; bcopy(buf, pkt, bufsz); - return bufsz; + return (bufsz); } if (status != EFI_NOT_READY) - return 0; + return (0); } - return 0; + return (0); } -void +static void efinet_init(struct iodesc *desc, void *machdep_hint) { struct netif *nif = desc->io_netif; EFI_SIMPLE_NETWORK *net; + EFI_HANDLE h; EFI_STATUS status; - net = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; - nif->nif_devdata = net; + h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private; + status = BS->HandleProtocol(h, &sn_guid, (VOID **)&nif->nif_devdata); + if (status != EFI_SUCCESS) { + printf("net%d: cannot start interface (status=%ld)\n", + nif->nif_unit, (long)status); + return; + } + net = nif->nif_devdata; if (net->Mode->State == EfiSimpleNetworkStopped) { status = net->Start(net); if (status != EFI_SUCCESS) { printf("net%d: cannot start interface (status=%ld)\n", - nif->nif_unit, status); + nif->nif_unit, (long)status); return; } } @@ -175,7 +203,7 @@ efinet_init(struct iodesc *desc, void *machdep_hint) status = net->Initialize(net, 0, 0); if (status != EFI_SUCCESS) { printf("net%d: cannot init. interface (status=%ld)\n", - nif->nif_unit, status); + nif->nif_unit, (long)status); return; } } @@ -187,7 +215,7 @@ efinet_init(struct iodesc *desc, void *machdep_hint) status = net->ReceiveFilters(net, mask, 0, FALSE, 0, 0); if (status != EFI_SUCCESS) { printf("net%d: cannot set rx. filters (status=%ld)\n", - nif->nif_unit, status); + nif->nif_unit, (long)status); return; } } @@ -198,71 +226,84 @@ efinet_init(struct iodesc *desc, void *machdep_hint) bcopy(net->Mode->CurrentAddress.Addr, desc->myea, 6); desc->xid = 1; +} + +static void +efinet_end(struct netif *nif) +{ + EFI_SIMPLE_NETWORK *net = nif->nif_devdata; - return; + net->Shutdown(net); } -void -efinet_init_driver() +static int efinet_dev_init(void); +static void efinet_dev_print(int); + +struct devsw efinet_dev = { + .dv_name = "net", + .dv_type = DEVT_NET, + .dv_init = efinet_dev_init, + .dv_strategy = net_strategy, + .dv_open = net_open, + .dv_close = net_close, + .dv_ioctl = noioctl, + .dv_print = efinet_dev_print, + .dv_cleanup = NULL +}; + +static int +efinet_dev_init() { - EFI_STATUS status; - UINTN sz; - static EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL; - EFI_HANDLE *handles; - int nifs, i; -#define MAX_INTERFACES 4 - static struct netif_dif difs[MAX_INTERFACES]; - static struct netif_stats stats[MAX_INTERFACES]; + struct netif_dif *dif; + struct netif_stats *stats; + EFI_HANDLE *handles; + EFI_STATUS status; + UINTN sz; + int err, i, nifs; sz = 0; - status = BS->LocateHandle(ByProtocol, &netid, 0, &sz, 0); - if (status != EFI_BUFFER_TOO_SMALL) - return; - handles = (EFI_HANDLE *) malloc(sz); - status = BS->LocateHandle(ByProtocol, &netid, 0, &sz, handles); - if (EFI_ERROR(status)) { - free(handles); - return; + status = BS->LocateHandle(ByProtocol, &sn_guid, 0, &sz, 0); + if (status == EFI_BUFFER_TOO_SMALL) { + handles = (EFI_HANDLE *)malloc(sz); + status = BS->LocateHandle(ByProtocol, &sn_guid, 0, &sz, + handles); + if (EFI_ERROR(status)) + free(handles); } - + if (EFI_ERROR(status)) + return (efi_status_to_errno(status)); nifs = sz / sizeof(EFI_HANDLE); - if (nifs > MAX_INTERFACES) - nifs = MAX_INTERFACES; + err = efi_register_handles(&efinet_dev, handles, nifs); + free(handles); + if (err != 0) + return (err); - efi_net.netif_nifs = nifs; - efi_net.netif_ifs = difs; + efinetif.netif_nifs = nifs; + efinetif.netif_ifs = calloc(nifs, sizeof(struct netif_dif)); + + stats = calloc(nifs, sizeof(struct netif_stats)); - bzero(stats, sizeof(stats)); for (i = 0; i < nifs; i++) { - struct netif_dif *dif = &efi_net.netif_ifs[i]; + dif = &efinetif.netif_ifs[i]; dif->dif_unit = i; dif->dif_nsel = 1; dif->dif_stats = &stats[i]; - - BS->HandleProtocol(handles[i], &netid, - (VOID**) &dif->dif_private); + dif->dif_private = efi_find_handle(&efinet_dev, i); } - return; + return (0); } -void -efinet_end(struct netif *nif) +static void +efinet_dev_print(int verbose) { - EFI_SIMPLE_NETWORK *net = nif->nif_devdata; - - net->Shutdown(net); + char line[80]; + EFI_HANDLE h; + int unit; + + for (unit = 0, h = efi_find_handle(&efinet_dev, 0); + h != NULL; h = efi_find_handle(&efinet_dev, ++unit)) { + sprintf(line, " %s%d:\n", efinet_dev.dv_name, unit); + pager_output(line); + } } - -struct netif_driver efi_net = { - "net", /* netif_bname */ - efinet_match, /* netif_match */ - efinet_probe, /* netif_probe */ - efinet_init, /* netif_init */ - efinet_get, /* netif_get */ - efinet_put, /* netif_put */ - efinet_end, /* netif_end */ - 0, /* netif_ifs */ - 0 /* netif_nifs */ -}; - diff --git a/sys/boot/efi/libefi/elf_freebsd.c b/sys/boot/efi/libefi/elf_freebsd.c deleted file mode 100644 index 93cfdbd..0000000 --- a/sys/boot/efi/libefi/elf_freebsd.c +++ /dev/null @@ -1,212 +0,0 @@ -/* $NetBSD: loadfile.c,v 1.10 1998/06/25 06:45:46 ross Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)boot.c 8.1 (Berkeley) 6/10/93 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> - -#include <sys/param.h> -#include <sys/linker.h> -#include <machine/elf.h> -#include <machine/bootinfo.h> -#include <machine/ia64_cpu.h> -#include <machine/pte.h> -#include <machine/vmparam.h> - -#include <efi.h> -#include <efilib.h> - -#include "bootstrap.h" - -#define _KERNEL - -static int elf64_exec(struct preloaded_file *amp); - -struct file_format ia64_elf = { elf64_loadfile, elf64_exec }; - -static __inline u_int64_t -disable_ic() -{ - u_int64_t psr; - __asm __volatile("mov %0=psr;;" : "=r" (psr)); - __asm __volatile("rsm psr.ic|psr.i;; srlz.i;;"); - return psr; -} - -static __inline void -restore_ic(u_int64_t psr) -{ - __asm __volatile("mov psr.l=%0;; srlz.i" :: "r" (psr)); -} - -/* - * Entered with psr.ic and psr.i both zero. - */ -void -enter_kernel(u_int64_t start, struct bootinfo *bi) -{ - u_int64_t psr; - - __asm __volatile("srlz.i;;"); - __asm __volatile("mov cr.ipsr=%0" - :: "r"(IA64_PSR_IC - | IA64_PSR_DT - | IA64_PSR_RT - | IA64_PSR_IT - | IA64_PSR_BN)); - __asm __volatile("mov cr.iip=%0" :: "r"(start)); - __asm __volatile("mov cr.ifs=r0;;"); - __asm __volatile("mov ar.rsc=0;; flushrs;;"); - __asm __volatile("mov r8=%0" :: "r" (bi)); - __asm __volatile("rfi;;"); -} - -static int -elf64_exec(struct preloaded_file *fp) -{ - struct file_metadata *md; - Elf_Ehdr *hdr; - pt_entry_t pte; - struct bootinfo *bi; - u_int64_t psr; - UINTN mapkey, pages, size; - UINTN descsz; - UINT32 descver; - EFI_STATUS status; - - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) - return(EFTYPE); /* XXX actually EFUCKUP */ - hdr = (Elf_Ehdr *)&(md->md_data); - - /* - * 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. - */ - size = 0; - descsz = sizeof(EFI_MEMORY_DESCRIPTOR); - BS->GetMemoryMap(&size, NULL, &mapkey, &descsz, &descver); - size += descsz + ((sizeof(struct bootinfo) + 0x0f) & ~0x0f); - pages = EFI_SIZE_TO_PAGES(size); - status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, - (void*)&bi); - if (EFI_ERROR(status)) { - printf("unable to create bootinfo block (status=0x%lx)\n", - (long)status); - return (ENOMEM); - } - - bzero(bi, sizeof(struct bootinfo)); - bi_load(bi, fp, &mapkey, pages); - - printf("Entering %s at 0x%lx...\n", fp->f_name, hdr->e_entry); - - status = BS->ExitBootServices(IH, mapkey); - if (EFI_ERROR(status)) { - printf("ExitBootServices returned 0x%lx\n", status); - return (EINVAL); - } - - psr = disable_ic(); - - /* - * Region 6 is direct mapped UC and region 7 is direct mapped - * WC. The details of this is controlled by the Alt {I,D}TLB - * handlers. Here we just make sure that they have the largest - * possible page size to minimise TLB usage. - */ - ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (28 << 2)); - ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2)); - - pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY | - PTE_PL_KERN | PTE_AR_RWX; - - __asm __volatile("mov cr.ifa=%0" :: "r"(IA64_RR_BASE(7))); - __asm __volatile("mov cr.itir=%0" :: "r"(28 << 2)); - __asm __volatile("ptr.i %0,%1" :: "r"(IA64_RR_BASE(7)), "r"(28<<2)); - __asm __volatile("ptr.d %0,%1" :: "r"(IA64_RR_BASE(7)), "r"(28<<2)); - __asm __volatile("srlz.i;;"); - __asm __volatile("itr.i itr[%0]=%1;;" :: "r"(0), "r"(pte)); - __asm __volatile("srlz.i;;"); - __asm __volatile("itr.d dtr[%0]=%1;;" :: "r"(0), "r"(pte)); - __asm __volatile("srlz.i;;"); - - enter_kernel(hdr->e_entry, bi); - - restore_ic(psr); -} diff --git a/sys/boot/efi/libefi/errno.c b/sys/boot/efi/libefi/errno.c new file mode 100644 index 0000000..fac903f --- /dev/null +++ b/sys/boot/efi/libefi/errno.c @@ -0,0 +1,94 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <efi.h> +#include <efilib.h> + +int +efi_status_to_errno(EFI_STATUS status) +{ + int errno; + + switch (status) { + case EFI_ACCESS_DENIED: + errno = EPERM; + break; + + case EFI_BUFFER_TOO_SMALL: + errno = EOVERFLOW; + break; + + case EFI_DEVICE_ERROR: + case EFI_VOLUME_CORRUPTED: + errno = EIO; + break; + + case EFI_INVALID_PARAMETER: + errno = EINVAL; + break; + + case EFI_MEDIA_CHANGED: + errno = ESTALE; + break; + + case EFI_NO_MEDIA: + errno = ENXIO; + break; + + case EFI_NOT_FOUND: + errno = ENOENT; + break; + + case EFI_OUT_OF_RESOURCES: + errno = ENOMEM; + break; + + case EFI_UNSUPPORTED: + errno = ENODEV; + break; + + case EFI_VOLUME_FULL: + errno = ENOSPC; + break; + + case EFI_WRITE_PROTECTED: + errno = EACCES; + break; + + case 0: + errno = 0; + break; + + default: + errno = EDOOFUS; + break; + } + + return (errno); +} diff --git a/sys/boot/efi/libefi/handles.c b/sys/boot/efi/libefi/handles.c new file mode 100644 index 0000000..7c78a15 --- /dev/null +++ b/sys/boot/efi/libefi/handles.c @@ -0,0 +1,90 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <efi.h> +#include <efilib.h> + +struct entry { + EFI_HANDLE handle; + struct devsw *dev; + int unit; +}; + +struct entry *entry; +int nentries; + +int +efi_register_handles(struct devsw *sw, EFI_HANDLE *handles, int count) +{ + size_t sz; + int idx, unit; + + idx = nentries; + nentries += count; + sz = nentries * sizeof(struct entry); + entry = (entry == NULL) ? malloc(sz) : realloc(entry, sz); + for (unit = 0; idx < nentries; idx++, unit++) { + entry[idx].handle = handles[unit]; + entry[idx].dev = sw; + entry[idx].unit = unit; + } + return (0); +} + +EFI_HANDLE +efi_find_handle(struct devsw *dev, int unit) +{ + int idx; + + for (idx = 0; idx < nentries; idx++) { + if (entry[idx].dev != dev) + continue; + if (entry[idx].unit != unit) + continue; + return (entry[idx].handle); + } + return (NULL); +} + +int +efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit) +{ + int idx; + + for (idx = 0; idx < nentries; idx++) { + if (entry[idx].handle != h) + continue; + if (dev != NULL) + *dev = entry[idx].dev; + if (unit != NULL) + *unit = entry[idx].unit; + return (0); + } + return (ENOENT); +} diff --git a/sys/boot/efi/libefi/module.c b/sys/boot/efi/libefi/module.c deleted file mode 100644 index 7a3f4b2..0000000 --- a/sys/boot/efi/libefi/module.c +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> - -/* - * Use voodoo to load modules required by current hardware. - */ -int -efi_autoload(void) -{ - /* XXX use PnP to locate stuff here */ - return (0); -} diff --git a/sys/boot/efi/libefi/time.c b/sys/boot/efi/libefi/time.c index 4cdba6b..5c39415 100644 --- a/sys/boot/efi/libefi/time.c +++ b/sys/boot/efi/libefi/time.c @@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$"); #define SECSPERDAY (24 * SECSPERHOUR) time_t -EfiTimeToUnixTime(EFI_TIME *ETime) +efi_time(EFI_TIME *ETime) { /* // These arrays give the cumulative number of days up to the first of the @@ -170,15 +170,15 @@ EFI_GetTimeOfDay( OUT struct timezone *tzp ) { - EFI_TIME EfiTime; + EFI_TIME EfiTime; EFI_TIME_CAPABILITIES Capabilities; - EFI_STATUS Status; + EFI_STATUS Status; /* // Get time from EFI */ - Status = RS->GetTime( &EfiTime, &Capabilities ); + Status = RS->GetTime(&EfiTime, &Capabilities); if (EFI_ERROR(Status)) return (-1); @@ -186,7 +186,7 @@ EFI_GetTimeOfDay( // Convert to UNIX time (ie seconds since the epoch */ - tp->tv_sec = EfiTimeToUnixTime( &EfiTime ); + tp->tv_sec = efi_time( &EfiTime ); tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */ /* diff --git a/sys/boot/ia64/Makefile b/sys/boot/ia64/Makefile index 7d19869..eb07ab8 100644 --- a/sys/boot/ia64/Makefile +++ b/sys/boot/ia64/Makefile @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= efi ski +SUBDIR= common efi ski .include <bsd.subdir.mk> diff --git a/sys/boot/ia64/common/Makefile b/sys/boot/ia64/common/Makefile new file mode 100644 index 0000000..b410bd8 --- /dev/null +++ b/sys/boot/ia64/common/Makefile @@ -0,0 +1,40 @@ +# $FreeBSD$ + +.include <bsd.own.mk> + +LIB= ia64 +INTERNALLIB= + +SRCS= autoload.c bootinfo.c copy.c devicename.c exec.c + +CFLAGS+= -I${.CURDIR}/../../efi/include +CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_ARCH} +CFLAGS+= -I${.CURDIR}/../../.. +CFLAGS+= -I${.CURDIR}/../../../../lib/libstand + +.if ${MK_FORTH} != "no" +BOOT_FORTH= yes +CFLAGS+= -DBOOT_FORTH +CFLAGS+= -I${.CURDIR}/../../ficl +CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_ARCH} +.endif + +.PATH: ${.CURDIR}/../../common +.include "${.CURDIR}/../../common/Makefile.inc" + +CFLAGS+= -I${.CURDIR}/../../common + +FILES+= loader.help +CLEANFILES+= loader.help +loader.help: help.common + cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk \ + > ${.TARGET} + +.PATH: ${.CURDIR}/../../forth +FILES+= loader.4th support.4th loader.conf +.if !exists(${DESTDIR}/boot/loader.rc) +FILES+= loader.rc +.endif +FILESDIR_loader.conf= /boot/defaults + +.include <bsd.lib.mk> diff --git a/sys/boot/ia64/common/autoload.c b/sys/boot/ia64/common/autoload.c new file mode 100644 index 0000000..ea334b9 --- /dev/null +++ b/sys/boot/ia64/common/autoload.c @@ -0,0 +1,35 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +int +ia64_autoload(void) +{ + + return (0); +} diff --git a/sys/boot/ia64/common/bootinfo.c b/sys/boot/ia64/common/bootinfo.c index bfda81d..6f892a9 100644 --- a/sys/boot/ia64/common/bootinfo.c +++ b/sys/boot/ia64/common/bootinfo.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,15 +33,11 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/reboot.h> #include <sys/linker.h> -#include <machine/elf.h> -#include <machine/bootinfo.h> #include <efi.h> #include <efilib.h> -#include "bootstrap.h" - -static EFI_GUID hcdp = HCDP_TABLE_GUID; +#include "libia64.h" /* * Return a 'boothowto' value corresponding to the kernel arguments in @@ -48,92 +45,60 @@ static EFI_GUID hcdp = HCDP_TABLE_GUID; */ static struct { - const char *ev; - int mask; + 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} + { "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} }; -extern char *efi_fmtdev(void *vdev); +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) { - char *cp; - int howto; - int active; - int i; - - /* Parse kargs */ - howto = 0; - if (kargs != NULL) { - cp = kargs; - active = 0; - while (*cp != 0) { - if (!active && (*cp == '-')) { - active = 1; - } else if (active) - switch (*cp) { - case 'a': - howto |= RB_ASKNAME; - break; - case 'C': - howto |= RB_CDROM; - break; - case 'd': - howto |= RB_KDB; - break; - case 'D': - howto |= RB_MULTIPLE; - break; - case 'm': - howto |= RB_MUTE; - break; - case 'g': - howto |= RB_GDB; - break; - case 'h': - howto |= RB_SERIAL; - break; - case 'p': - howto |= RB_PAUSE; - break; - case 'r': - howto |= RB_DFLTROOT; - break; - case 's': - howto |= RB_SINGLE; - break; - case 'v': - howto |= RB_VERBOSE; - break; - default: - active = 0; - break; + 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]; } - cp++; + opts = strchr(opts, '-'); } - } - /* get equivalents from the environment */ - for (i = 0; howto_names[i].ev != NULL; i++) - if (getenv(howto_names[i].ev) != NULL) - howto |= howto_names[i].mask; - if (!strcmp(getenv("console"), "comconsole")) - howto |= RB_SERIAL; - if (!strcmp(getenv("console"), "nullconsole")) - howto |= RB_MUTE; - return(howto); + + return (howto); } /* @@ -142,26 +107,37 @@ bi_getboothowto(char *kargs) * separating each variable, and a double nul terminating the environment. */ vm_offset_t -bi_copyenv(vm_offset_t addr) +bi_copyenv(vm_offset_t start) { - struct env_var *ep; - - /* traverse the environment */ - for (ep = environ; ep != NULL; ep = ep->ev_next) { - efi_copyin(ep->ev_name, addr, strlen(ep->ev_name)); - addr += strlen(ep->ev_name); - efi_copyin("=", addr, 1); - addr++; - if (ep->ev_value != NULL) { - efi_copyin(ep->ev_value, addr, strlen(ep->ev_value)); - addr += strlen(ep->ev_value); + 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 (ia64_copyin(ep->ev_name, addr, len) != len) + break; + addr += len; + if (ia64_copyin("=", addr, 1) != 1) + break; + addr++; + if (ep->ev_value != NULL) { + len = strlen(ep->ev_value); + if (ia64_copyin(ep->ev_value, addr, len) != len) + break; + addr += len; + } + if (ia64_copyin("", addr, 1) != 1) + break; + last = ++addr; } - efi_copyin("", addr, 1); - addr++; - } - efi_copyin("", addr, 1); - addr++; - return(addr); + + if (ia64_copyin("", last++, 1) != 1) + last = start; + return(last); } /* @@ -182,14 +158,14 @@ bi_copyenv(vm_offset_t addr) */ #define COPY32(v, a) { \ u_int32_t x = (v); \ - efi_copyin(&x, a, sizeof(x)); \ + ia64_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s) { \ COPY32(t, a); \ COPY32(strlen(s) + 1, a); \ - efi_copyin(s, a, strlen(s) + 1); \ + ia64_copyin(s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(u_int64_t));\ } @@ -200,7 +176,7 @@ bi_copyenv(vm_offset_t addr) #define MOD_VAR(t, a, s) { \ COPY32(t, a); \ COPY32(sizeof(s), a); \ - efi_copyin(&s, a, sizeof(s)); \ + ia64_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_int64_t)); \ } @@ -210,7 +186,7 @@ bi_copyenv(vm_offset_t addr) #define MOD_METADATA(a, mm) { \ COPY32(MODINFO_METADATA | mm->md_type, a); \ COPY32(mm->md_size, a); \ - efi_copyin(mm->md_data, a, mm->md_size); \ + ia64_copyin(mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(u_int64_t));\ } @@ -222,24 +198,25 @@ bi_copyenv(vm_offset_t addr) 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) { - - MOD_NAME(addr, fp->f_name); /* this field must come first */ - 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); + 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); } /* @@ -249,103 +226,71 @@ bi_copymodules(vm_offset_t addr) * - Module metadata are formatted and placed in kernel space. */ int -bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey, - UINTN pages) +bi_load(struct preloaded_file *fp, uint64_t *bi_addr) { - char *rootdevname; - struct efi_devdesc *rootdev; - struct preloaded_file *xp; - vm_offset_t addr, bootinfo_addr; - vm_offset_t ssym, esym; - struct file_metadata *md; - EFI_STATUS status; - UINTN bisz, key; - - /* - * Version 1 bootinfo. - */ - bi->bi_magic = BOOTINFO_MAGIC; - bi->bi_version = 1; - - /* - * Calculate boothowto. - */ - bi->bi_boothowto = bi_getboothowto(fp->f_args); - - /* - * Stash EFI System Table. - */ - bi->bi_systab = (u_int64_t) ST; - - /* - * 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"); - efi_getdev((void **)(&rootdev), rootdevname, NULL); - if (rootdev == NULL) { /* bad $rootdev/$currdev */ - printf("can't determine root device\n"); - return(EINVAL); - } - - /* Try reading the /etc/fstab file to select the root device */ - getrootmount(efi_fmtdev((void *)rootdev)); - free(rootdev); - - ssym = esym = 0; - if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL) - ssym = *((vm_offset_t *)&(md->md_data)); - if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL) - esym = *((vm_offset_t *)&(md->md_data)); - if (ssym == 0 || esym == 0) - ssym = esym = 0; /* sanity */ - - bi->bi_symtab = ssym; - bi->bi_esymtab = esym; - - bi->bi_hcdp = (uint64_t)efi_get_table(&hcdp); /* DIG64 HCDP table addr. */ - fpswa_init(&bi->bi_fpswa); /* find FPSWA interface */ - - /* 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; - } - - /* pad to a page boundary */ - addr = (addr + PAGE_MASK) & ~PAGE_MASK; - - /* copy our environment */ - bi->bi_envp = addr; - addr = bi_copyenv(addr); - - /* pad to a page boundary */ - addr = (addr + PAGE_MASK) & ~PAGE_MASK; - - /* copy module list and metadata */ - bi->bi_modulep = addr; - addr = bi_copymodules(addr); - - /* all done copying stuff in, save end of loaded object space */ - bi->bi_kernend = addr; - - /* - * Read the memory map and stash it after bootinfo. Align the memory map - * on a 16-byte boundary (the bootinfo block is page aligned). - */ - bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; - bi->bi_memmap = ((u_int64_t)bi) + bisz; - bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz; - status = BS->GetMemoryMap(&bi->bi_memmap_size, - (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key, - &bi->bi_memdesc_size, &bi->bi_memdesc_version); - if (EFI_ERROR(status)) { - printf("bi_load: Can't read memory map\n"); - return EINVAL; - } - *mapkey = key; - - return(0); + 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_magic = BOOTINFO_MAGIC; + 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"); + ia64_getdev((void**)&rootdev, rootdevname, NULL); + if (rootdev != NULL) { + /* Try reading /etc/fstab to select the root device. */ + getrootmount(ia64_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)); } diff --git a/sys/boot/ia64/common/copy.c b/sys/boot/ia64/common/copy.c index 4b4b9bd..5583b15 100644 --- a/sys/boot/ia64/common/copy.c +++ b/sys/boot/ia64/common/copy.c @@ -1,55 +1,118 @@ /*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * 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. + * 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 <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <efi.h> -#include <efilib.h> #include <stand.h> +#include <ia64/include/vmparam.h> + +#include "libia64.h" + +#define LDR_LOG2_PGSZ 20 + +uint64_t *ia64_pgtbl; +uint32_t ia64_pgtblsz; + +static void * +va2pa(vm_offset_t va, size_t *len) +{ + uint64_t pa; + + if (va >= IA64_RR_BASE(7)) { + pa = IA64_RR_MASK(va); + return ((void *)pa); + } + + printf("\n%s: va=%lx, *len=%lx\n", __func__, va, *len); + *len = 0; + return (NULL); +} -int -efi_copyin(void *src, vm_offset_t va, size_t len) +ssize_t +ia64_copyin(const void *src, vm_offset_t va, size_t len) { + void *pa; + ssize_t res; + size_t sz; - bcopy(src, (void *)efimd_va2pa(va), len); - return (len); + res = 0; + while (len > 0) { + sz = len; + pa = va2pa(va, &sz); + if (sz == 0) + break; + bcopy(src, pa, sz); + len -= sz; + res += sz; + va += sz; + } + return (res); } -int -efi_copyout(vm_offset_t va, void *dst, size_t len) +ssize_t +ia64_copyout(vm_offset_t va, void *dst, size_t len) { + void *pa; + ssize_t res; + size_t sz; - bcopy((void *)efimd_va2pa(va), dst, len); - return (len); + res = 0; + while (len > 0) { + sz = len; + pa = va2pa(va, &sz); + if (sz == 0) + break; + bcopy(pa, dst, sz); + len -= sz; + res += sz; + va += sz; + } + return (res); } -int -efi_readin(int fd, vm_offset_t va, size_t len) +ssize_t +ia64_readin(int fd, vm_offset_t va, size_t len) { + void *pa; + ssize_t res, s; + size_t sz; - return (read(fd, (void *)efimd_va2pa(va), len)); + res = 0; + while (len > 0) { + sz = len; + pa = va2pa(va, &sz); + if (sz == 0) + break; + s = read(fd, pa, sz); + if (s <= 0) + break; + len -= s; + res += s; + va += s; + } + return (res); } diff --git a/sys/boot/ia64/common/devicename.c b/sys/boot/ia64/common/devicename.c index 62c943a..08d9b54 100644 --- a/sys/boot/ia64/common/devicename.c +++ b/sys/boot/ia64/common/devicename.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,9 +35,8 @@ __FBSDID("$FreeBSD$"); #include <efi.h> #include <efilib.h> -#include "efiboot.h" -static int efi_parsedev(struct efi_devdesc **dev, const char *devspec, const char **path); +static int ia64_parsedev(struct devdesc **, const char *, const char **); /* * Point (dev) at an allocated device specifier for the device matching the @@ -44,29 +44,24 @@ static int efi_parsedev(struct efi_devdesc **dev, const char *devspec, const cha * use that. If not, use the default device. */ int -efi_getdev(void **vdev, const char *devspec, const char **path) +ia64_getdev(void **vdev, const char *devspec, const char **path) { - struct efi_devdesc **dev = (struct efi_devdesc **)vdev; - int rv; - + struct devdesc **dev = (struct devdesc **)vdev; + int rv; + /* - * If it looks like this is just a path and no - * device, go with the current device. + * If it looks like this is just a path and no device, then + * use the current device instead. */ - if ((devspec == NULL) || - (devspec[0] == '/') || - (strchr(devspec, ':') == NULL)) { - - if (((rv = efi_parsedev(dev, getenv("currdev"), NULL)) == 0) && - (path != NULL)) + if (devspec == NULL || *devspec == '/' || !strchr(devspec, ':')) { + rv = ia64_parsedev(dev, getenv("currdev"), NULL); + if (rv == 0 && path != NULL) *path = devspec; - return(rv); + return (rv); } - - /* - * Try to parse the device name off the beginning of the devspec - */ - return(efi_parsedev(dev, devspec, path)); + + /* Parse the device name off the beginning of the devspec. */ + return (ia64_parsedev(dev, devspec, path)); } /* @@ -80,162 +75,95 @@ efi_getdev(void **vdev, const char *devspec, const char **path) * * For disk-type devices, the syntax is: * - * disk<unit>[s<slice>][<partition>]: - * + * fs<unit>: */ static int -efi_parsedev(struct efi_devdesc **dev, const char *devspec, const char **path) +ia64_parsedev(struct devdesc **dev, const char *devspec, const char **path) { - struct efi_devdesc *idev; - struct devsw *dv; - int i, unit, slice, partition, err; - char *cp; - const char *np; + struct devdesc *idev; + struct devsw *dv; + char *cp; + const char *np; + int i, err; /* minimum length check */ if (strlen(devspec) < 2) - return(EINVAL); + return (EINVAL); /* look for a device that matches */ - for (i = 0, dv = NULL; devsw[i] != NULL; i++) { - if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { - dv = devsw[i]; + 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); - if (dv == NULL) - return(ENOENT); - idev = malloc(sizeof(struct efi_devdesc)); - err = 0; - np = (devspec + strlen(dv->dv_name)); - - switch(dv->dv_type) { - case DEVT_NONE: /* XXX what to do here? Do we care? */ - break; - - case DEVT_DISK: - unit = -1; - slice = -1; - partition = -1; - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 10); /* next comes the unit number */ - if (cp == np) { - err = EUNIT; - goto fail; - } - if (*cp == 's') { /* got a slice number */ - np = cp + 1; - slice = strtol(np, &cp, 10); - if (cp == np) { - err = ESLICE; - goto fail; - } - } - if (*cp && (*cp != ':')) { - partition = *cp - 'a'; /* get a partition number */ - if ((partition < 0) || (partition >= MAXPARTITIONS)) { - err = EPART; - goto fail; - } - cp++; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } + idev = malloc(sizeof(struct devdesc)); + if (idev == NULL) + return (ENOMEM); - idev->d_unit = unit; - idev->d_kind.efidisk.slice = slice; - idev->d_kind.efidisk.partition = partition; + idev->d_dev = dv; + idev->d_type = dv->dv_type; + idev->d_unit = -1; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - case DEVT_NET: - unit = 0; - - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 0); /* get unit number if present */ - if (cp == np) { - err = EUNIT; - goto fail; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; + 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); } - - idev->d_unit = unit; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - default: - err = EINVAL; - goto fail; } - idev->d_dev = dv; - idev->d_type = dv->dv_type; - if (dev == NULL) { + if (*cp != '\0' && *cp != ':') { free(idev); - } else { - *dev = idev; + return (EINVAL); } - return(0); - fail: - free(idev); - return(err); + if (path != NULL) + *path = (*cp == 0) ? cp : cp + 1; + if (dev != NULL) + *dev = idev; + else + free(idev); + return (0); } - char * -efi_fmtdev(void *vdev) +ia64_fmtdev(void *vdev) { - struct efi_devdesc *dev = (struct efi_devdesc *)vdev; - static char buf[128]; /* XXX device length constant? */ - char *cp; - + 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; - case DEVT_DISK: - cp = buf; - cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_unit); - if (dev->d_kind.efidisk.slice > 0) - cp += sprintf(cp, "s%d", dev->d_kind.efidisk.slice); - if (dev->d_kind.efidisk.partition >= 0) - cp += sprintf(cp, "%c", dev->d_kind.efidisk.partition + 'a'); - strcat(cp, ":"); - break; - - case DEVT_NET: + 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 -efi_setcurrdev(struct env_var *ev, int flags, void *value) +ia64_setcurrdev(struct env_var *ev, int flags, const void *value) { - struct efi_devdesc *ncurr; - int rv; - - if ((rv = efi_parsedev(&ncurr, value, NULL)) != 0) + struct devdesc *ncurr; + int rv; + + rv = ia64_parsedev(&ncurr, value, NULL); + if (rv != 0) return(rv); + free(ncurr); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - return(0); + return (0); } - diff --git a/sys/boot/ia64/common/exec.c b/sys/boot/ia64/common/exec.c index 93cfdbd..a5a02d4 100644 --- a/sys/boot/ia64/common/exec.c +++ b/sys/boot/ia64/common/exec.c @@ -1,73 +1,27 @@ -/* $NetBSD: loadfile.c,v 1.10 1998/06/25 06:45:46 ross Exp $ */ - /*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center. - * * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ -/* - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * - * @(#)boot.c 8.1 (Berkeley) 6/10/93 + * 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 <sys/cdefs.h> @@ -79,10 +33,11 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/linker.h> #include <machine/elf.h> -#include <machine/bootinfo.h> #include <machine/ia64_cpu.h> #include <machine/pte.h> -#include <machine/vmparam.h> + +#include <ia64/include/bootinfo.h> +#include <ia64/include/vmparam.h> #include <efi.h> #include <efilib.h> @@ -95,28 +50,12 @@ static int elf64_exec(struct preloaded_file *amp); struct file_format ia64_elf = { elf64_loadfile, elf64_exec }; -static __inline u_int64_t -disable_ic() -{ - u_int64_t psr; - __asm __volatile("mov %0=psr;;" : "=r" (psr)); - __asm __volatile("rsm psr.ic|psr.i;; srlz.i;;"); - return psr; -} - -static __inline void -restore_ic(u_int64_t psr) -{ - __asm __volatile("mov psr.l=%0;; srlz.i" :: "r" (psr)); -} - /* * Entered with psr.ic and psr.i both zero. */ void -enter_kernel(u_int64_t start, struct bootinfo *bi) +enter_kernel(uint64_t start, uint64_t bi) { - u_int64_t psr; __asm __volatile("srlz.i;;"); __asm __volatile("mov cr.ipsr=%0" @@ -130,6 +69,8 @@ enter_kernel(u_int64_t start, struct bootinfo *bi) __asm __volatile("mov ar.rsc=0;; flushrs;;"); __asm __volatile("mov r8=%0" :: "r" (bi)); __asm __volatile("rfi;;"); + + /* NOTREACHED */ } static int @@ -138,51 +79,21 @@ elf64_exec(struct preloaded_file *fp) struct file_metadata *md; Elf_Ehdr *hdr; pt_entry_t pte; - struct bootinfo *bi; - u_int64_t psr; - UINTN mapkey, pages, size; - UINTN descsz; - UINT32 descver; - EFI_STATUS status; - - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) - return(EFTYPE); /* XXX actually EFUCKUP */ + uint64_t bi_addr; + + md = file_findmetadata(fp, MODINFOMD_ELFHDR); + if (md == NULL) + return (EINVAL); hdr = (Elf_Ehdr *)&(md->md_data); - /* - * 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. - */ - size = 0; - descsz = sizeof(EFI_MEMORY_DESCRIPTOR); - BS->GetMemoryMap(&size, NULL, &mapkey, &descsz, &descver); - size += descsz + ((sizeof(struct bootinfo) + 0x0f) & ~0x0f); - pages = EFI_SIZE_TO_PAGES(size); - status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, - (void*)&bi); - if (EFI_ERROR(status)) { - printf("unable to create bootinfo block (status=0x%lx)\n", - (long)status); - return (ENOMEM); - } - - bzero(bi, sizeof(struct bootinfo)); - bi_load(bi, fp, &mapkey, pages); + bi_load(fp, &bi_addr); printf("Entering %s at 0x%lx...\n", fp->f_name, hdr->e_entry); - status = BS->ExitBootServices(IH, mapkey); - if (EFI_ERROR(status)) { - printf("ExitBootServices returned 0x%lx\n", status); - return (EINVAL); - } + ldr_enter(fp->f_name); - psr = disable_ic(); + __asm __volatile("rsm psr.ic|psr.i;;"); + __asm __volatile("srlz.i;;"); /* * Region 6 is direct mapped UC and region 7 is direct mapped @@ -206,7 +117,8 @@ elf64_exec(struct preloaded_file *fp) __asm __volatile("itr.d dtr[%0]=%1;;" :: "r"(0), "r"(pte)); __asm __volatile("srlz.i;;"); - enter_kernel(hdr->e_entry, bi); + enter_kernel(hdr->e_entry, bi_addr); - restore_ic(psr); + /* NOTREACHED */ + return (0); } diff --git a/sys/boot/ia64/common/libia64.h b/sys/boot/ia64/common/libia64.h new file mode 100644 index 0000000..53de341 --- /dev/null +++ b/sys/boot/ia64/common/libia64.h @@ -0,0 +1,61 @@ +/*- + * 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. + * + * $FreeBSD$ + */ + +#ifndef _LIBIA64_H_ +#define _LIBIA64_H_ + +#include <bootstrap.h> +#include <ia64/include/bootinfo.h> + +/* + * Portability functions provided by the loader + * implementation specific to the platform. + */ +extern uint64_t ldr_alloc(vm_offset_t); +extern int ldr_bootinfo(struct bootinfo *, uint64_t *); +extern int ldr_enter(const char *); + +/* + * Functions and variables provided by the ia64 common code + * and shared by all loader implementations. + */ + +extern uint64_t *ia64_pgtbl; +extern uint32_t ia64_pgtblsz; + +extern int ia64_autoload(void); + +extern ssize_t ia64_copyin(const void *, vm_offset_t, size_t); +extern ssize_t ia64_copyout(vm_offset_t, void *, size_t); +extern ssize_t ia64_readin(int, vm_offset_t, size_t); + +extern char *ia64_fmtdev(struct devdesc *); +extern int ia64_getdev(void **, const char *, const char **); +extern int ia64_setcurrdev(struct env_var *, int, const void *); + +#endif /* !_LIBIA64_H_ */ diff --git a/sys/boot/ia64/efi/Makefile b/sys/boot/ia64/efi/Makefile index f5fed73..0c07610 100644 --- a/sys/boot/ia64/efi/Makefile +++ b/sys/boot/ia64/efi/Makefile @@ -6,44 +6,22 @@ NO_MAN= PROG= loader.sym INTERNALPROG= -SRCS= conf.c dev_net.c efimd.c main.c start.S vers.c +SRCS= conf.c efimd.c main.c pal.S start.S vers.c -CFLAGS+= -DLOADER +.PATH: ${.CURDIR}/../../../${MACHINE_ARCH}/${MACHINE_ARCH} + +CFLAGS+= -I${.CURDIR}/../common +CFLAGS+= -I${.CURDIR}/../../common CFLAGS+= -I${.CURDIR}/../../efi/include CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_ARCH} -CFLAGS+= -I${.CURDIR}/../../efi/libefi +CFLAGS+= -I${.CURDIR}/../../.. CFLAGS+= -I${.CURDIR}/../../../../lib/libstand -.if ${MK_FORTH} != "no" -BOOT_FORTH= yes -CFLAGS+= -DBOOT_FORTH -CFLAGS+= -I${.CURDIR}/../../ficl -CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_ARCH} -LIBFICL= ${.OBJDIR}/../../ficl/libficl.a -.endif - -# Always add MI sources -.PATH: ${.CURDIR}/../../common -.include "${.CURDIR}/../../common/Makefile.inc" - -CFLAGS+= -I${.CURDIR}/../../common - -.PATH: ${.CURDIR}/../../forth -FILES= loader.efi loader.help loader.4th support.4th loader.conf -FILESMODE_loader.efi= ${BINMODE} -FILESDIR_loader.conf= /boot/defaults - -.if !exists(${DESTDIR}/boot/loader.rc) -FILES+= loader.rc -.endif - LDSCRIPT= ${.CURDIR}/ldscript.${MACHINE_ARCH} LDFLAGS= -Wl,-T${LDSCRIPT} -shared -symbolic ${PROG}: ${LDSCRIPT} -CLEANFILES= vers.c loader.efi loader.help - NEWVERSWHAT= "EFI boot" ${MACHINE_ARCH} vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version @@ -52,22 +30,29 @@ vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version OBJCOPY?= objcopy OBJDUMP?= objdump +FILES= loader.efi +FILESMODE_loader.efi= ${BINMODE} + loader.efi: loader.sym if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ + rm ${.ALLSRC}; \ exit 1; \ fi ${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \ -j .rela.dyn -j .reloc -j .sdata -j .text \ --target=efi-app-${MACHINE_ARCH} ${.ALLSRC} ${.TARGET} -loader.help: help.common - cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk \ - > ${.TARGET} +CLEANFILES= vers.c loader.efi +LIBIA64= ${.OBJDIR}/../common/libia64.a LIBEFI= ${.OBJDIR}/../../efi/libefi/libefi.a +.if ${MK_FORTH} != "no" +LIBFICL= ${.OBJDIR}/../../ficl/libficl.a +.endif -DPADD= ${LIBFICL} ${LIBEFI} ${LIBSTAND} -LDADD= ${LIBFICL} ${LIBEFI} -lstand +DPADD= ${LIBIA64} ${LIBFICL} ${LIBEFI} ${LIBSTAND} +LDADD= -Wl,--whole-archive ${LIBIA64} -Wl,--no-whole-archive \ + ${LIBFICL} ${LIBEFI} -lstand .include <bsd.prog.mk> diff --git a/sys/boot/ia64/efi/conf.c b/sys/boot/ia64/efi/conf.c index 8a250e6..a72f79f 100644 --- a/sys/boot/ia64/efi/conf.c +++ b/sys/boot/ia64/efi/conf.c @@ -38,8 +38,6 @@ __FBSDID("$FreeBSD$"); #include <efi.h> #include <efilib.h> -#include "efiboot.h" - /* * We could use linker sets for some or all of these, but * then we would have to control what ended up linked into @@ -52,24 +50,23 @@ __FBSDID("$FreeBSD$"); /* Exported for libstand */ struct devsw *devsw[] = { &efifs_dev, - &netdev, + &efinet_dev, NULL }; struct fs_ops *file_system[] = { - &efi_fsops, -/* &ufs_fsops, */ + &efifs_fsops, &nfs_fsops, + &ufs_fsops, &gzipfs_fsops, NULL }; struct netif_driver *netif_drivers[] = { - &efi_net, - NULL, + &efinetif, + NULL }; -/* Exported for ia64 only */ /* * Sort formats so that those that can detect based on arguments * rather than reading the file go first. diff --git a/sys/boot/ia64/efi/efimd.c b/sys/boot/ia64/efi/efimd.c index accf6c2..8a1e0c7 100644 --- a/sys/boot/ia64/efi/efimd.c +++ b/sys/boot/ia64/efi/efimd.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2004 Marcel Moolenaar + * Copyright (c) 2004, 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +27,112 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <stand.h> + #include <efi.h> #include <efilib.h> -#include <machine/vmparam.h> +#include <libia64.h> + +#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; -EFI_PHYSICAL_ADDRESS -efimd_va2pa(EFI_VIRTUAL_ADDRESS va) + /* + * 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 (IA64_RR_MASK(va)); + return (0); } diff --git a/sys/boot/ia64/efi/main.c b/sys/boot/ia64/efi/main.c index 2d11bed..9419903 100644 --- a/sys/boot/ia64/efi/main.c +++ b/sys/boot/ia64/efi/main.c @@ -39,16 +39,19 @@ __FBSDID("$FreeBSD$"); #include <efi.h> #include <efilib.h> -#include "bootstrap.h" -#include "efiboot.h" +#include <libia64.h> +/* DIG64 Headless Console & Debug Port Table. */ +#define HCDP_TABLE_GUID \ + {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}} + extern char bootprog_name[]; extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; -struct efi_devdesc currdev; /* our current device */ -struct arch_switch archsw; /* MI/MD interface boundary */ +struct devdesc currdev; /* our current device */ +struct arch_switch archsw; /* MI/MD interface boundary */ extern u_int64_t ia64_pal_entry; @@ -121,8 +124,6 @@ main(int argc, CHAR16 *argv[]) if (devsw[i]->dv_init != NULL) (devsw[i]->dv_init)(); - efinet_init_driver(); - /* Get our loaded image protocol interface structure. */ BS->HandleProtocol(IH, &imgid, (VOID**)&img); @@ -132,17 +133,7 @@ main(int argc, CHAR16 *argv[]) printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); - i = efifs_get_unit(img->DeviceHandle); - if (i >= 0) { - currdev.d_dev = devsw[0]; /* XXX disk */ - currdev.d_unit = i; - /* XXX should be able to detect this, default to autoprobe */ - currdev.d_kind.efidisk.slice = -1; - currdev.d_kind.efidisk.partition = 0; - } else { - currdev.d_dev = devsw[1]; /* XXX net */ - currdev.d_unit = 0; /* XXX */ - } + efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit); currdev.d_type = currdev.d_dev->dv_type; /* @@ -156,18 +147,18 @@ main(int argc, CHAR16 *argv[]) */ BS->SetWatchdogTimer(0, 0, 0, NULL); - env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev), - efi_setcurrdev, env_nounset); - env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset, + env_setenv("currdev", EV_VOLATILE, ia64_fmtdev(&currdev), + ia64_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset, env_nounset); setenv("LINES", "24", 1); /* optional */ - archsw.arch_autoload = efi_autoload; - archsw.arch_getdev = efi_getdev; - archsw.arch_copyin = efi_copyin; - archsw.arch_copyout = efi_copyout; - archsw.arch_readin = efi_readin; + archsw.arch_autoload = ia64_autoload; + archsw.arch_getdev = ia64_getdev; + archsw.arch_copyin = ia64_copyin; + archsw.arch_copyout = ia64_copyout; + archsw.arch_readin = ia64_readin; interact(); /* doesn't return */ diff --git a/sys/boot/ia64/efi/version b/sys/boot/ia64/efi/version index 71f9400..7d7f566 100644 --- a/sys/boot/ia64/efi/version +++ b/sys/boot/ia64/efi/version @@ -3,6 +3,7 @@ $FreeBSD$ NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this file is important. Make sure the current version number is on line 6. +1.2: Restructured. Has some user visible differences. 1.1: Pass the HCDP table address to the kernel via bootinfo if one is present in the EFI system table. 1.0: Don't map the I/O port range. We expect the kernel to do it. It diff --git a/sys/boot/ia64/ski/Makefile b/sys/boot/ia64/ski/Makefile index 84b06dc..42d24d1 100644 --- a/sys/boot/ia64/ski/Makefile +++ b/sys/boot/ia64/ski/Makefile @@ -5,45 +5,34 @@ NO_MAN= .include <bsd.own.mk> PROG= skiload -NEWVERSWHAT= "ia64 SKI boot" ${MACHINE_ARCH} STRIP= # We must not strip skiload at install time. -SRCS= acpi_stub.c bootinfo.c conf.c copy.c delay.c devicename.c \ - efi_stub.c elf_freebsd.c exit.c main.c pal_stub.S sal_stub.c \ - skiconsole.c skifs.c ssc.c start.S time.c vers.c +SRCS= acpi_stub.c conf.c delay.c efi_stub.c exit.c main.c \ + pal_stub.S sal_stub.c skiconsole.c skifs.c skimd.c \ + ssc.c start.S time.c vers.c -CFLAGS+= -DLOADER -CFLAGS+= -I${.CURDIR} -CFLAGS+= -I${.CURDIR}/../../.. -CFLAGS+= -I${.CURDIR}/../../efi/include -CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_ARCH} -LDFLAGS= -Wl,-T${.CURDIR}/ldscript.ia64 - -.if ${MK_FORTH} != "no" -CFLAGS+= -DBOOT_FORTH -CFLAGS+= -I${.CURDIR}/../../ficl -CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_ARCH} -LIBFICL= ${.OBJDIR}/../../ficl/libficl.a -BOOT_FORTH= yes -.endif - -# Always add MI sources (needs BOOT_FORTH) -.PATH: ${.CURDIR}/../../common +CFLAGS+= -I${.CURDIR}/../common CFLAGS+= -I${.CURDIR}/../../common -.include "${.CURDIR}/../../common/Makefile.inc" +CFLAGS+= -I${.CURDIR}/../../.. +CFLAGS+= -I${.CURDIR}/../../../../lib/libstand -DPADD= ${LIBFICL} ${LIBSTAND} -LDADD= ${LIBFICL} -lstand +LDSCRIPT= ${.CURDIR}/ldscript.${MACHINE_ARCH} +LDFLAGS= -Wl,-T${LDSCRIPT} -CLEANFILES= vers.c ${PROG}.help +NEWVERSWHAT= "SKI boot" ${MACHINE_ARCH} vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} -${PROG}.help: help.common - cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk \ - > ${.TARGET} +CLEANFILES= vers.c + +LIBIA64= ${.OBJDIR}/../common/libia64.a +.if ${MK_FORTH} != "no" +LIBFICL= ${.OBJDIR}/../../ficl/libficl.a +.endif -FILES= ${PROG}.help +DPADD= ${LIBIA64} ${LIBFICL} ${LIBSTAND} +LDADD= -Wl,--whole-archive ${LIBIA64} -Wl,--no-whole-archive \ + ${LIBFICL} -lstand .include <bsd.prog.mk> diff --git a/sys/boot/ia64/ski/bootinfo.c b/sys/boot/ia64/ski/bootinfo.c deleted file mode 100644 index 4c19d22..0000000 --- a/sys/boot/ia64/ski/bootinfo.c +++ /dev/null @@ -1,321 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> -#include <sys/param.h> -#include <sys/reboot.h> -#include <sys/linker.h> -#include <machine/elf.h> -#include <machine/bootinfo.h> - -#include "bootstrap.h" - -/* - * 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} -}; - -extern char *ski_fmtdev(void *vdev); -extern int ski_init_stubs(struct bootinfo *); - -int -bi_getboothowto(char *kargs) -{ - char *cp; - int howto; - int active; - int i; - - /* Parse kargs */ - howto = 0; - if (kargs != NULL) { - cp = kargs; - active = 0; - while (*cp != 0) { - if (!active && (*cp == '-')) { - active = 1; - } else if (active) - switch (*cp) { - case 'a': - howto |= RB_ASKNAME; - break; - case 'C': - howto |= RB_CDROM; - break; - case 'd': - howto |= RB_KDB; - break; - case 'D': - howto |= RB_MULTIPLE; - break; - case 'm': - howto |= RB_MUTE; - break; - case 'g': - howto |= RB_GDB; - break; - case 'h': - howto |= RB_SERIAL; - break; - case 'p': - howto |= RB_PAUSE; - break; - case 'r': - howto |= RB_DFLTROOT; - break; - case 's': - howto |= RB_SINGLE; - break; - case 'v': - howto |= RB_VERBOSE; - break; - default: - active = 0; - break; - } - cp++; - } - } - /* get equivalents from the environment */ - for (i = 0; howto_names[i].ev != NULL; i++) - if (getenv(howto_names[i].ev) != NULL) - howto |= howto_names[i].mask; - if (!strcmp(getenv("console"), "comconsole")) - howto |= RB_SERIAL; - if (!strcmp(getenv("console"), "nullconsole")) - howto |= RB_MUTE; - return(howto); -} - -/* - * Copy the environment into the load area starting at (addr). - * Each variable is formatted as <name>=<value>, with a single nul - * separating each variable, and a double nul terminating the environment. - */ -vm_offset_t -bi_copyenv(vm_offset_t addr) -{ - struct env_var *ep; - - /* traverse the environment */ - for (ep = environ; ep != NULL; ep = ep->ev_next) { - ski_copyin(ep->ev_name, addr, strlen(ep->ev_name)); - addr += strlen(ep->ev_name); - ski_copyin("=", addr, 1); - addr++; - if (ep->ev_value != NULL) { - ski_copyin(ep->ev_value, addr, strlen(ep->ev_value)); - addr += strlen(ep->ev_value); - } - ski_copyin("", addr, 1); - addr++; - } - ski_copyin("", addr, 1); - addr++; - return(addr); -} - -/* - * 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); \ - ski_copyin(&x, a, sizeof(x)); \ - a += sizeof(x); \ -} - -#define MOD_STR(t, a, s) { \ - COPY32(t, a); \ - COPY32(strlen(s) + 1, a); \ - ski_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); \ - ski_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); \ - ski_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) { - - MOD_NAME(addr, fp->f_name); /* this field must come first */ - 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 bootinfo *bi, struct preloaded_file *fp, char *args) -{ - char *rootdevname; - struct ski_devdesc *rootdev; - struct preloaded_file *xp; - vm_offset_t addr, bootinfo_addr; - char *kernelname; - vm_offset_t ssym, esym; - struct file_metadata *md; - - /* - * Version 1 bootinfo. - */ - bi->bi_magic = BOOTINFO_MAGIC; - bi->bi_version = 1; - - /* - * Calculate boothowto. - */ - 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"); - ski_getdev((void **)(&rootdev), rootdevname, NULL); - if (rootdev == NULL) { /* bad $rootdev/$currdev */ - printf("can't determine root device\n"); - return(EINVAL); - } - - /* Try reading the /etc/fstab file to select the root device */ - getrootmount(ski_fmtdev((void *)rootdev)); - free(rootdev); - - ssym = esym = 0; - if ((md = file_findmetadata(fp, MODINFOMD_SSYM)) != NULL) - ssym = *((vm_offset_t *)&(md->md_data)); - if ((md = file_findmetadata(fp, MODINFOMD_ESYM)) != NULL) - esym = *((vm_offset_t *)&(md->md_data)); - if (ssym == 0 || esym == 0) - ssym = esym = 0; /* sanity */ - - 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; - } - - /* pad to a page boundary */ - addr = (addr + PAGE_MASK) & ~PAGE_MASK; - - /* copy our environment */ - bi->bi_envp = addr; - addr = bi_copyenv(addr); - - /* pad to a page boundary */ - addr = (addr + PAGE_MASK) & ~PAGE_MASK; - - /* copy module list and metadata */ - bi->bi_modulep = addr; - addr = bi_copymodules(addr); - - /* all done copying stuff in, save end of loaded object space */ - bi->bi_kernend = addr; - - return (ski_init_stubs(bi)); -} diff --git a/sys/boot/ia64/ski/copy.c b/sys/boot/ia64/ski/copy.c deleted file mode 100644 index d86537a..0000000 --- a/sys/boot/ia64/ski/copy.c +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * MD primitives supporting placement of module data - * - * XXX should check load address/size against memory top. - */ -#include <stand.h> - -#include <machine/ia64_cpu.h> -#include <machine/vmparam.h> - -int -ski_copyin(void *src, vm_offset_t dest, size_t len) -{ - bcopy(src, (void*) IA64_RR_MASK(dest), len); - return (len); -} - -int -ski_copyout(vm_offset_t src, void *dest, size_t len) -{ - bcopy((void*) IA64_RR_MASK(src), dest, len); - return (len); -} - -int -ski_readin(int fd, vm_offset_t dest, size_t len) -{ - return (read(fd, (void*) IA64_RR_MASK(dest), len)); -} diff --git a/sys/boot/ia64/ski/devicename.c b/sys/boot/ia64/ski/devicename.c deleted file mode 100644 index 1a3a75d..0000000 --- a/sys/boot/ia64/ski/devicename.c +++ /dev/null @@ -1,238 +0,0 @@ -/*- - * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> - * 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 <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> -#include <sys/disklabel.h> -#include "bootstrap.h" -#include "libski.h" - -static int ski_parsedev(struct ski_devdesc **dev, const char *devspec, const char **path); - -/* - * 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 -ski_getdev(void **vdev, const char *devspec, const char **path) -{ - struct ski_devdesc **dev = (struct ski_devdesc **)vdev; - int rv; - - /* - * If it looks like this is just a path and no - * device, go with the current device. - */ - if ((devspec == NULL) || - (devspec[0] == '/') || - (strchr(devspec, ':') == NULL)) { - - if (((rv = ski_parsedev(dev, getenv("currdev"), NULL)) == 0) && - (path != NULL)) - *path = devspec; - return(rv); - } - - /* - * Try to parse the device name off the beginning of the devspec - */ - return(ski_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: - * - * disk<unit>[s<slice>][<partition>]: - * - */ -static int -ski_parsedev(struct ski_devdesc **dev, const char *devspec, const char **path) -{ - struct ski_devdesc *idev; - struct devsw *dv; - int i, unit, slice, partition, err; - char *cp; - const char *np; - - /* minimum length check */ - if (strlen(devspec) < 2) - return(EINVAL); - - /* look for a device that matches */ - for (i = 0, dv = NULL; devsw[i] != NULL; i++) { - if (!strncmp(devspec, devsw[i]->dv_name, strlen(devsw[i]->dv_name))) { - dv = devsw[i]; - break; - } - } - - if (dv == NULL) - return(ENOENT); - idev = malloc(sizeof(struct ski_devdesc)); - err = 0; - np = (devspec + strlen(dv->dv_name)); - - switch(dv->dv_type) { - case DEVT_NONE: /* XXX what to do here? Do we care? */ - break; - - case DEVT_DISK: - unit = -1; - slice = -1; - partition = -1; - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 10); /* next comes the unit number */ - if (cp == np) { - err = EUNIT; - goto fail; - } - if (*cp == 's') { /* got a slice number */ - np = cp + 1; - slice = strtol(np, &cp, 10); - if (cp == np) { - err = ESLICE; - goto fail; - } - } - if (*cp && (*cp != ':')) { - partition = *cp - 'a'; /* get a partition number */ - if ((partition < 0) || (partition >= MAXPARTITIONS)) { - err = EPART; - goto fail; - } - cp++; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - - idev->d_unit = unit; - idev->d_kind.skidisk.slice = slice; - idev->d_kind.skidisk.partition = partition; - - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - case DEVT_NET: - unit = 0; - - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 0); /* get unit number if present */ - if (cp == np) { - err = EUNIT; - goto fail; - } - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - - idev->d_unit = unit; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; - break; - - default: - err = EINVAL; - goto fail; - } - idev->d_dev = dv; - idev->d_type = dv->dv_type; - if (dev == NULL) { - free(idev); - } else { - *dev = idev; - } - return(0); - - fail: - free(idev); - return(err); -} - - -char * -ski_fmtdev(void *vdev) -{ - struct ski_devdesc *dev = (struct ski_devdesc *)vdev; - static char buf[128]; /* XXX device length constant? */ - char *cp; - - switch(dev->d_type) { - case DEVT_NONE: - strcpy(buf, "(no device)"); - break; - - case DEVT_DISK: - cp = buf; - cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_unit); - if (dev->d_kind.skidisk.slice > 0) - cp += sprintf(cp, "s%d", dev->d_kind.skidisk.slice); - if (dev->d_kind.skidisk.partition >= 0) - cp += sprintf(cp, "%c", dev->d_kind.skidisk.partition + 'a'); - strcat(cp, ":"); - break; - - case DEVT_NET: - 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 -ski_setcurrdev(struct env_var *ev, int flags, void *value) -{ - struct ski_devdesc *ncurr; - int rv; - - if ((rv = ski_parsedev(&ncurr, value, NULL)) != 0) - return(rv); - free(ncurr); - env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); - return(0); -} - diff --git a/sys/boot/ia64/ski/efi_stub.c b/sys/boot/ia64/ski/efi_stub.c index 20a20b4..3c7a099 100644 --- a/sys/boot/ia64/ski/efi_stub.c +++ b/sys/boot/ia64/ski/efi_stub.c @@ -28,17 +28,14 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> -#include <machine/bootinfo.h> #include <machine/efi.h> +#include <ia64/include/bootinfo.h> #include <stand.h> #include "libski.h" extern void acpi_root; extern void sal_systab; -extern void acpi_stub_init(void); -extern void sal_stub_init(void); - struct efi_cfgtbl efi_cfgtab[] = { { EFI_TABLE_ACPI20, (intptr_t)&acpi_root }, { EFI_TABLE_SAL, (intptr_t)&sal_systab } @@ -223,8 +220,8 @@ ResetSystem(enum efi_reset type, efi_status status, u_long datasz, return (unsupported(__func__)); } -int -ski_init_stubs(struct bootinfo *bi) +void +efi_stub_init(struct bootinfo *bi) { struct efi_md *memp; @@ -261,9 +258,4 @@ ski_init_stubs(struct bootinfo *bi) memp[3].md_attr = EFI_MD_ATTR_UC; bi->bi_systab = (u_int64_t)&efi_systab; - - sal_stub_init(); - acpi_stub_init(); - - return (0); } diff --git a/sys/boot/ia64/ski/elf_freebsd.c b/sys/boot/ia64/ski/elf_freebsd.c deleted file mode 100644 index 42481d6..0000000 --- a/sys/boot/ia64/ski/elf_freebsd.c +++ /dev/null @@ -1,202 +0,0 @@ -/* $NetBSD: loadfile.c,v 1.10 1998/06/25 06:45:46 ross Exp $ */ - -/*- - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. - */ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell. - * - * 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)boot.c 8.1 (Berkeley) 6/10/93 - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stand.h> -#include <string.h> - -#include <sys/param.h> -#include <sys/linker.h> -#include <machine/elf.h> -#include <machine/bootinfo.h> -#include <machine/ia64_cpu.h> -#include <machine/vmparam.h> - -#include "bootstrap.h" -#include "libski.h" - -#define _KERNEL - -static int elf64_exec(struct preloaded_file *amp); - -struct file_format ia64_elf = { elf64_loadfile, elf64_exec }; - -#define PTE_MA_WB 0 -#define PTE_MA_UC 4 -#define PTE_MA_UCE 5 -#define PTE_MA_WC 6 -#define PTE_MA_NATPAGE 7 - -#define PTE_PL_KERN 0 -#define PTE_PL_USER 3 - -#define PTE_AR_R 0 -#define PTE_AR_RX 1 -#define PTE_AR_RW 2 -#define PTE_AR_RWX 3 -#define PTE_AR_R_RW 4 -#define PTE_AR_RX_RWX 5 -#define PTE_AR_RWX_RW 6 -#define PTE_AR_X_RX 7 - -/* - * A short-format VHPT entry. Also matches the TLB insertion format. - */ -struct ia64_pte { - u_int64_t pte_p :1; /* bits 0..0 */ - u_int64_t pte_rv1 :1; /* bits 1..1 */ - u_int64_t pte_ma :3; /* bits 2..4 */ - u_int64_t pte_a :1; /* bits 5..5 */ - u_int64_t pte_d :1; /* bits 6..6 */ - u_int64_t pte_pl :2; /* bits 7..8 */ - u_int64_t pte_ar :3; /* bits 9..11 */ - u_int64_t pte_ppn :38; /* bits 12..49 */ - u_int64_t pte_rv2 :2; /* bits 50..51 */ - u_int64_t pte_ed :1; /* bits 52..52 */ - u_int64_t pte_ig :11; /* bits 53..63 */ -}; - -static struct bootinfo bootinfo; - -void -enter_kernel(const char* filename, u_int64_t start, struct bootinfo *bi) -{ - printf("Entering %s at 0x%lx...\n", filename, start); - - while (*filename == '/') - filename++; - ssc(0, (u_int64_t) filename, 0, 0, SSC_LOAD_SYMBOLS); - - __asm __volatile("mov cr.ipsr=%0" - :: "r"(IA64_PSR_IC - | IA64_PSR_DT - | IA64_PSR_RT - | IA64_PSR_IT - | IA64_PSR_BN)); - __asm __volatile("mov cr.iip=%0" :: "r"(start)); - __asm __volatile("mov cr.ifs=r0;;"); - __asm __volatile("mov r8=%0" :: "r" (bi)); - __asm __volatile("rfi;;"); -} - -static int -elf64_exec(struct preloaded_file *fp) -{ - struct file_metadata *md; - Elf_Ehdr *hdr; - struct ia64_pte pte; - struct bootinfo *bi; - - if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) - return(EFTYPE); /* XXX actually EFUCKUP */ - hdr = (Elf_Ehdr *)&(md->md_data); - - /* - * Ugly hack, similar to linux. Dump the bootinfo into a - * special page reserved in the link map. - */ - bi = &bootinfo; - bzero(bi, sizeof(struct bootinfo)); - bi_load(bi, fp); - - /* - * Region 6 is direct mapped UC and region 7 is direct mapped - * WC. The details of this is controlled by the Alt {I,D}TLB - * handlers. Here we just make sure that they have the largest - * possible page size to minimise TLB usage. - */ - ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (28 << 2)); - ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (28 << 2)); - - bzero(&pte, sizeof(pte)); - pte.pte_p = 1; - pte.pte_ma = PTE_MA_WB; - pte.pte_a = 1; - pte.pte_d = 1; - pte.pte_pl = PTE_PL_KERN; - pte.pte_ar = PTE_AR_RWX; - pte.pte_ppn = 0; - - __asm __volatile("mov cr.ifa=%0" :: "r"(IA64_RR_BASE(7))); - __asm __volatile("mov cr.itir=%0" :: "r"(28 << 2)); - __asm __volatile("srlz.i;;"); - __asm __volatile("itr.i itr[%0]=%1;;" - :: "r"(0), "r"(*(u_int64_t*)&pte)); - __asm __volatile("srlz.i;;"); - __asm __volatile("itr.d dtr[%0]=%1;;" - :: "r"(0), "r"(*(u_int64_t*)&pte)); - __asm __volatile("srlz.i;;"); - - enter_kernel(fp->f_name, hdr->e_entry, bi); -} diff --git a/sys/boot/ia64/ski/libski.h b/sys/boot/ia64/ski/libski.h index 595e59a..5bbc6de 100644 --- a/sys/boot/ia64/ski/libski.h +++ b/sys/boot/ia64/ski/libski.h @@ -26,28 +26,6 @@ * $FreeBSD$ */ -/* - * SKI fully-qualified device descriptor - */ -struct ski_devdesc { - struct devsw *d_dev; - int d_type; -#define DEVT_NONE 0 -#define DEVT_DISK 1 -#define DEVT_NET 2 - int d_unit; - union { - struct { - int slice; - int partition; - } skidisk; - } d_kind; -}; - -extern int ski_getdev(void **vdev, const char *devspec, const char **path); -extern char *ski_fmtdev(void *vdev); -extern int ski_setcurrdev(struct env_var *ev, int flags, void *value); - #define MAXDEV 31 /* maximum number of distinct devices */ typedef unsigned long physaddr_t; @@ -64,10 +42,6 @@ extern struct fs_ops ski_fsops; extern void delay(int); extern void reboot(void); -extern ssize_t ski_copyin(const void *src, vm_offset_t dest, size_t len); -extern ssize_t ski_copyout(const vm_offset_t src, void *dest, size_t len); -extern ssize_t ski_readin(int fd, vm_offset_t dest, size_t len); - extern int ski_boot(void); struct bootinfo; diff --git a/sys/boot/ia64/ski/main.c b/sys/boot/ia64/ski/main.c index 604553c..6cfa25b 100644 --- a/sys/boot/ia64/ski/main.c +++ b/sys/boot/ia64/ski/main.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$"); #include <setjmp.h> #include <machine/fpu.h> -#include "bootstrap.h" +#include <libia64.h> #include "libski.h" extern char bootprog_name[]; @@ -41,15 +41,8 @@ extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; -struct ski_devdesc currdev; /* our current device */ -struct arch_switch archsw; /* MI/MD interface boundary */ - -static int -ski_autoload(void) -{ - - return (0); -} +struct devdesc currdev; /* our current device */ +struct arch_switch archsw; /* MI/MD interface boundary */ void ski_main(void) @@ -85,15 +78,11 @@ ski_main(void) #if 0 printf("Memory: %ld k\n", memsize() / 1024); #endif - + /* XXX presumes that biosdisk is first in devsw */ currdev.d_dev = devsw[0]; currdev.d_type = currdev.d_dev->dv_type; currdev.d_unit = 0; - /* XXX should be able to detect this, default to autoprobe */ - currdev.d_kind.skidisk.slice = -1; - /* default to 'a' */ - currdev.d_kind.skidisk.partition = 0; #if 0 /* Create arc-specific variables */ @@ -102,18 +91,18 @@ ski_main(void) setenv("bootfile", bootfile, 1); #endif - env_setenv("currdev", EV_VOLATILE, ski_fmtdev(&currdev), - ski_setcurrdev, env_nounset); - env_setenv("loaddev", EV_VOLATILE, ski_fmtdev(&currdev), env_noset, + env_setenv("currdev", EV_VOLATILE, ia64_fmtdev(&currdev), + ia64_setcurrdev, env_nounset); + env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset, env_nounset); setenv("LINES", "24", 1); /* optional */ - archsw.arch_autoload = ski_autoload; - archsw.arch_getdev = ski_getdev; - archsw.arch_copyin = ski_copyin; - archsw.arch_copyout = ski_copyout; - archsw.arch_readin = ski_readin; + archsw.arch_autoload = ia64_autoload; + archsw.arch_getdev = ia64_getdev; + archsw.arch_copyin = ia64_copyin; + archsw.arch_copyout = ia64_copyout; + archsw.arch_readin = ia64_readin; interact(); /* doesn't return */ diff --git a/sys/boot/ia64/ski/skifs.c b/sys/boot/ia64/ski/skifs.c index 5a272c7..72276fe 100644 --- a/sys/boot/ia64/ski/skifs.c +++ b/sys/boot/ia64/ski/skifs.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <stand.h> #include <stdarg.h> +#include <bootstrap.h> #include "libski.h" struct disk_req { diff --git a/sys/boot/ia64/ski/skimd.c b/sys/boot/ia64/ski/skimd.c new file mode 100644 index 0000000..bec2ec0 --- /dev/null +++ b/sys/boot/ia64/ski/skimd.c @@ -0,0 +1,74 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stand.h> + +#include <libia64.h> + +#include "libski.h" + +#define PHYS_START (4L*1024*1024*1024) +#define PHYS_SIZE (64L*1024*1024 - 4L*1024) + +extern void acpi_stub_init(void); +extern void efi_stub_init(struct bootinfo *); +extern void sal_stub_init(void); + +uint64_t +ldr_alloc(vm_offset_t va) +{ + + if (va >= PHYS_SIZE) + return (0); + return (va + PHYS_START); +} + +int +ldr_bootinfo(struct bootinfo *bi, uint64_t *bi_addr) +{ + static struct bootinfo bootinfo; + + efi_stub_init(bi); + sal_stub_init(); + acpi_stub_init(); + + *bi_addr = (uint64_t)(&bootinfo); + bootinfo = *bi; + return (0); +} + +int +ldr_enter(const char *kernel) +{ + + while (*kernel == '/') + kernel++; + ssc(0, (uint64_t)kernel, 0, 0, SSC_LOAD_SYMBOLS); + return (0); +} diff --git a/sys/boot/ia64/ski/version b/sys/boot/ia64/ski/version index 6f4fc3c..afa69ea 100644 --- a/sys/boot/ia64/ski/version +++ b/sys/boot/ia64/ski/version @@ -3,6 +3,9 @@ $FreeBSD$ NOTE ANY CHANGES YOU MAKE TO THE BOOTBLOCKS HERE. The format of this file is important. Make sure the current version number is on line 6. +1.2: Restructured. Has some user visible differences. Due to code + sharing, has been given the same version number as the EFI + loader. 0.2: Pass the address of the bootinfo block to the kernel in register r8. Keep it at the hardwired address for now. 0.1: Initial SKI version. |