diff options
Diffstat (limited to 'sys/boot/ia64/common')
-rw-r--r-- | sys/boot/ia64/common/Makefile | 40 | ||||
-rw-r--r-- | sys/boot/ia64/common/autoload.c | 35 | ||||
-rw-r--r-- | sys/boot/ia64/common/bootinfo.c | 385 | ||||
-rw-r--r-- | sys/boot/ia64/common/copy.c | 113 | ||||
-rw-r--r-- | sys/boot/ia64/common/devicename.c | 202 | ||||
-rw-r--r-- | sys/boot/ia64/common/exec.c | 146 | ||||
-rw-r--r-- | sys/boot/ia64/common/libia64.h | 61 |
7 files changed, 483 insertions, 499 deletions
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_ */ |