Index: user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S (revision 276360) +++ user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S (revision 276361) @@ -1,36 +1,32 @@ #include ENTRY(host_read) li %r0, 3 # SYS_read sc blr ENTRY(host_write) li %r0, 4 # SYS_write sc blr ENTRY(host_seek) li %r0, 478 # SYS_lseek sc blr ENTRY(host_open) li %r0, 5 # SYS_open sc blr ENTRY(host_close) li %r0, 6 # SYS_close sc blr -ENTRY(host_getmem) /* addr, size */ - li %r5, 3 # PROT_READ | PROT_WRITE - li %r6, 0x1000 # MAP_ANON - li %r7, -1 - li %r8, 0 +ENTRY(host_mmap) li %r0, 477 # SYS_mmap sc blr Index: user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h (revision 276360) +++ user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h (revision 276361) @@ -1,40 +1,41 @@ /*- * Copyright (C) 2010 Nathan Whitehorn * 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 TOOLS GMBH 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 _HOST_SYSCALL_H #define _HOST_SYSCALL_H #include ssize_t host_read(int fd, void *buf, size_t nbyte); ssize_t host_write(int fd, const void *buf, size_t nbyte); ssize_t host_seek(int fd, uint64_t offset, int whence); int host_open(char *path, int flags, int mode); int host_close(int fd); -void *host_getmem(void *addr, size_t len); +void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t); +#define host_getmem(size) host_mmap(0, size, 3 /* RW */, 0x1000 /* ANON */, -1, 0); #endif Index: user/nwhitehorn/kboot/powerpc/kboot/main.c =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/main.c (revision 276360) +++ user/nwhitehorn/kboot/powerpc/kboot/main.c (revision 276361) @@ -1,218 +1,278 @@ /*- * Copyright (C) 2010-2014 Nathan Whitehorn * 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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #define _KERNEL #include #include "bootstrap.h" #include "host_syscall.h" struct arch_switch archsw; extern void *_end; extern char bootprog_name[]; extern char bootprog_rev[]; extern char bootprog_date[]; extern char bootprog_maker[]; int kboot_getdev(void **vdev, const char *devspec, const char **path); ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len); int kboot_autoload(void); int kboot_setcurrdev(struct env_var *ev, int flags, const void *value); int kboot_getdev(void **vdev, const char *devspec, const char **path) { int i; const char *devpath, *filepath; struct devsw *dv; struct devdesc *desc; if (strchr(devspec, ':') != NULL) { devpath = devspec; filepath = strchr(devspec, ':') + 1; } else { devpath = getenv("currdev"); - filepath = &devspec[1]; + filepath = devspec; } for (i = 0; (dv = devsw[i]) != NULL; i++) { if (strncmp(dv->dv_name, devpath, strlen(dv->dv_name)) == 0) goto found; } return (ENOENT); found: if (path != NULL && filepath != NULL) *path = filepath; else if (path != NULL) *path = strchr(devspec, ':') + 1; if (vdev != NULL) { desc = malloc(sizeof(*desc)); desc->d_dev = dv; desc->d_unit = 0; desc->d_opendata = strdup(devpath); *vdev = desc; } return (0); } int main(int argc, const char **argv) { void *heapbase; + const size_t heapsize = 15*1024*1024; /* * Set the heap to one page after the end of the loader. */ - heapbase = host_getmem(0, 0x100000); - setheap(heapbase, heapbase + 0x100000); + heapbase = host_getmem(heapsize); + setheap(heapbase, heapbase + heapsize); /* * Set up console. */ cons_probe(); printf("Boot device: %s\n", argv[1]); archsw.arch_getdev = kboot_getdev; archsw.arch_copyin = kboot_copyin; archsw.arch_copyout = kboot_copyout; archsw.arch_readin = kboot_readin; archsw.arch_autoload = kboot_autoload; printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); setenv("currdev", argv[1], 1); setenv("loaddev", argv[1], 1); setenv("LINES", "24", 1); interact(NULL); /* doesn't return */ return (0); } void exit(int code) { /* XXX: host_exit */ } void delay(int usecs) { /* XXX */ } int getsecs() { /* XXX */ return (0); } time_t time(time_t *tloc) { time_t rv; rv = getsecs(); if (tloc != NULL) *tloc = rv; return (rv); } +struct kexec_segment { + void *buf; + size_t bufsz; + void *mem; + size_t memsz; +}; + +struct kexec_segment loaded_segments[128]; +int nkexec_segments = 0; + +static ssize_t +get_phys_buffer(vm_offset_t dest, const size_t len, void **buf) +{ + int i = 0; + const size_t segsize = 2*1024*1024; + + for (i = 0; i < nkexec_segments; i++) { + if (dest >= (vm_offset_t)loaded_segments[i].mem && + dest < (vm_offset_t)loaded_segments[i].mem + + loaded_segments[i].memsz) + goto out; + } + + loaded_segments[nkexec_segments].buf = host_getmem(segsize); + loaded_segments[nkexec_segments].bufsz = segsize; + loaded_segments[nkexec_segments].mem = (void *)rounddown2(dest,segsize); + loaded_segments[nkexec_segments].memsz = segsize; + i = nkexec_segments; + nkexec_segments++; + +out: + *buf = loaded_segments[i].buf + (dest - + (vm_offset_t)loaded_segments[i].mem); + return (min(len,loaded_segments[i].bufsz - (dest - + (vm_offset_t)loaded_segments[i].mem))); +} + ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len) { - bcopy(src, (void *)dest, len); + ssize_t segsize, remainder; + void *destbuf; + + remainder = len; + do { + segsize = get_phys_buffer(dest, remainder, &destbuf); + bcopy(src, destbuf, segsize); + remainder -= segsize; + src += segsize; + dest += segsize; + } while (remainder > 0); + return (len); } ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len) { - bcopy((void *)src, dest, len); + ssize_t segsize, remainder; + void *srcbuf; + + remainder = len; + do { + segsize = get_phys_buffer(src, remainder, &srcbuf); + bcopy(srcbuf, dest, segsize); + remainder -= segsize; + src += segsize; + dest += segsize; + } while (remainder > 0); + return (len); } ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len) { void *buf; size_t resid, chunk, get; ssize_t got; vm_offset_t p; p = dest; chunk = min(PAGE_SIZE, len); buf = malloc(chunk); if (buf == NULL) { printf("kboot_readin: buf malloc failed\n"); - return(0); + return (0); } for (resid = len; resid > 0; resid -= got, p += got) { get = min(chunk, resid); got = read(fd, buf, get); if (got <= 0) { if (got < 0) printf("kboot_readin: read failed\n"); break; } - bcopy(buf, (void *)p, got); + kboot_copyin(buf, p, got); } - free(buf); + free (buf); return (len - resid); } int kboot_autoload(void) { return (0); } void _start(int argc, const char **argv, char **env) { main(argc, argv); } Index: user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c (revision 276360) +++ user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c (revision 276361) @@ -1,98 +1,92 @@ /*- * Copyright (c) 2001 Benno Rice * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define __ELF_WORD_SIZE 64 #include #include #include #include #include #include "bootstrap.h" extern char end[]; extern vm_offset_t reloc; /* From /conf.c */ int ppc64_elf_loadfile(char *filename, u_int64_t dest, struct preloaded_file **result) { int r; r = __elfN(loadfile)(filename, dest, result); if (r != 0) return (r); - /* - * No need to sync the icache for modules: this will - * be done by the kernel after relocation. - */ - if (!strcmp((*result)->f_type, "elf kernel")) - __syncicache((void *) (*result)->f_addr, (*result)->f_size); return (0); } int ppc64_elf_exec(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp; Elf_Ehdr *e; int error; int (*entry)(u_long, u_long, u_long, void *, u_long); if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; /* Handle function descriptor */ entry = (void *)(uintptr_t)(*(uint64_t *)e->e_entry); if ((error = md_load64(fp->f_args, &mdp)) != 0) return (error); printf("Kernel entry at %p ...\n", entry); dev_cleanup(); entry(0 /* FDT */, 0 /* Phys. mem offset */, 0 /* OF entry */, (void *)mdp, sizeof(mdp)); panic("exec returned"); } struct file_format ppc_elf64 = { ppc64_elf_loadfile, ppc64_elf_exec };