Index: user/nwhitehorn/kboot/fdt/Makefile =================================================================== --- user/nwhitehorn/kboot/fdt/Makefile (revision 276506) +++ user/nwhitehorn/kboot/fdt/Makefile (revision 276507) @@ -1,28 +1,29 @@ # $FreeBSD$ .PATH: ${.CURDIR}/../../contrib/libfdt/ LIB= fdt INTERNALLIB= # Vendor sources of libfdt. -SRCS+= fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +SRCS+= fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c \ + fdt_empty_tree.c # Loader's fdt commands extension sources. SRCS+= fdt_loader_cmd.c CFLAGS+= -I${.CURDIR}/../../contrib/libfdt/ -I${.CURDIR}/../common/ CFLAGS+= -ffreestanding .if ${MACHINE_CPUARCH} == "powerpc" || ${MACHINE_CPUARCH} == "arm" || ${MACHINE_CPUARCH} == "mips" CFLAGS+= -msoft-float .endif .if ${MACHINE_ARCH} == "powerpc64" CFLAGS+= -m32 .endif CFLAGS+= -Wformat -Wall .include Index: user/nwhitehorn/kboot/powerpc/kboot/Makefile =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/Makefile (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/Makefile (revision 276507) @@ -1,131 +1,131 @@ # $FreeBSD$ .include MK_SSP= no PROG= loader.kboot NEWVERSWHAT= "kboot loader" ${MACHINE_ARCH} BINDIR?= /boot INSTALLFLAGS= -b # Architecture-specific loader code SRCS= conf.c metadata.c vers.c main.c ppc64_elf_freebsd.c SRCS+= host_syscall.S hostcons.c hostdisk.c kerneltramp.S kbootfdt.c SRCS+= ucmpdi2.c LOADER_DISK_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_CD9660_SUPPORT?= yes LOADER_EXT2FS_SUPPORT?= yes LOADER_NET_SUPPORT?= yes LOADER_NFS_SUPPORT?= yes LOADER_TFTP_SUPPORT?= no LOADER_GZIP_SUPPORT?= yes -LOADER_FDT_SUPPORT?= yes +LOADER_FDT_SUPPORT= yes LOADER_BZIP2_SUPPORT?= no .if ${LOADER_DISK_SUPPORT} == "yes" CFLAGS+= -DLOADER_DISK_SUPPORT .endif .if ${LOADER_UFS_SUPPORT} == "yes" CFLAGS+= -DLOADER_UFS_SUPPORT .endif .if ${LOADER_CD9660_SUPPORT} == "yes" CFLAGS+= -DLOADER_CD9660_SUPPORT .endif .if ${LOADER_EXT2FS_SUPPORT} == "yes" CFLAGS+= -DLOADER_EXT2FS_SUPPORT .endif .if ${LOADER_GZIP_SUPPORT} == "yes" CFLAGS+= -DLOADER_GZIP_SUPPORT .endif .if ${LOADER_BZIP2_SUPPORT} == "yes" CFLAGS+= -DLOADER_BZIP2_SUPPORT .endif .if ${LOADER_NET_SUPPORT} == "yes" CFLAGS+= -DLOADER_NET_SUPPORT .endif .if ${LOADER_NFS_SUPPORT} == "yes" CFLAGS+= -DLOADER_NFS_SUPPORT .endif .if ${LOADER_TFTP_SUPPORT} == "yes" CFLAGS+= -DLOADER_TFTP_SUPPORT .endif .if ${LOADER_FDT_SUPPORT} == "yes" CFLAGS+= -I${.CURDIR}/../../fdt CFLAGS+= -I${.OBJDIR}/../../fdt CFLAGS+= -I${.CURDIR}/../../../contrib/libfdt CFLAGS+= -DLOADER_FDT_SUPPORT LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a .endif .if ${MK_FORTH} != "no" # Enable BootForth BOOT_FORTH= yes CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/powerpc LIBFICL= ${.OBJDIR}/../../ficl/libficl.a .endif # Avoid the open-close-dance for every file access as some firmwares perform # an auto-negotiation on every open of the network interface and thus causes # netbooting to take horribly long. CFLAGS+= -DNETIF_OPEN_CLOSE_ONCE -mcpu=powerpc64 # Always add MI sources .PATH: ${.CURDIR}/../../common ${.CURDIR}/../../../libkern .include "${.CURDIR}/../../common/Makefile.inc" CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../../.. CFLAGS+= -I. CLEANFILES+= vers.c loader.help CFLAGS+= -Wall -ffreestanding -msoft-float -DAIM # load address. set in linker script RELOC?= 0x0 CFLAGS+= -DRELOC=${RELOC} LDFLAGS= -nostdlib -static -T ${.CURDIR}/ldscript.powerpc # 64-bit bridge extensions CFLAGS+= -Wa,-mppc64bridge # Pull in common loader code #.PATH: ${.CURDIR}/../../ofw/common #.include "${.CURDIR}/../../ofw/common/Makefile.inc" # where to get libstand from LIBSTAND= ${.OBJDIR}/../../libstand32/libstand.a CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/ -DPADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND} -LDADD= ${LIBFICL} ${LIBOFW} ${LIBSTAND} +DPADD= ${LIBFICL} ${LIBOFW} ${LIBFDT} ${LIBSTAND} +LDADD= ${LIBFICL} ${LIBOFW} ${LIBFDT} ${LIBSTAND} SC_DFLT_FONT=cp437 font.h: uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x16.fnt && file2c 'u_char dflt_font_16[16*256] = {' '};' < ${SC_DFLT_FONT}-8x16 > font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x14.fnt && file2c 'u_char dflt_font_14[14*256] = {' '};' < ${SC_DFLT_FONT}-8x14 >> font.h && uudecode < /usr/share/syscons/fonts/${SC_DFLT_FONT}-8x8.fnt && file2c 'u_char dflt_font_8[8*256] = {' '};' < ${SC_DFLT_FONT}-8x8 >> font.h vers.c: ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT} loader.help: help.common help.kboot ${.CURDIR}/../../fdt/help.fdt cat ${.ALLSRC} | \ awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET} .PATH: ${.CURDIR}/../../forth FILES= loader.help loader.4th support.4th loader.conf FILES+= screen.4th frames.4th FILES+= beastie.4th brand.4th check-password.4th color.4th delay.4th FILES+= menu.4th menu-commands.4th menusets.4th shortcuts.4th version.4th FILESDIR_loader.conf= /boot/defaults .if !exists(${DESTDIR}/boot/loader.rc) FILES+= loader.rc .endif .if !exists(${DESTDIR}/boot/menu.rc) FILES+= menu.rc .endif .include Index: user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/host_syscall.S (revision 276507) @@ -1,71 +1,67 @@ #include ENTRY(host_read) li %r0, 3 # SYS_read sc bso 1f blr 1: - li %r3, -1 + li %r3, 0 blr + ENTRY(host_write) li %r0, 4 # SYS_write sc blr ENTRY(host_seek) li %r0, 19 # SYS_lseek sc blr ENTRY(host_open) li %r0, 5 # SYS_open sc bso 1f blr 1: li %r3, 0 blr ENTRY(host_close) li %r0, 6 # SYS_close sc blr ENTRY(host_mmap) li %r0, 90 # SYS_mmap sc blr ENTRY(host_gettimeofday) li %r0, 78 # SYS_gettimeofday sc blr ENTRY(host_select) li %r0, 142 # SYS_select sc blr ENTRY(kexec_load) - lis %r4,nkexec_segments@ha - ori %r4,%r4,nkexec_segments@l - lwz %r4,0(%r4) - lis %r5,loaded_segments@ha - ori %r5,%r5,loaded_segments@l lis %r6,21 # KEXEC_ARCH_PPC64 li %r0,268 # __NR_kexec_load sc blr ENTRY(host_reboot) li %r0,88 # SYS_reboot sc blr ENTRY(host_getdents) li %r0,141 # SYS_getdents sc blr Index: user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/host_syscall.h (revision 276507) @@ -1,51 +1,51 @@ /*- * Copyright (C) 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. * * $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, int offset, int whence); int host_open(char *path, int flags, int mode); int host_close(int fd); void *host_mmap(void *addr, size_t len, int prot, int flags, int fd, int); #define host_getmem(size) host_mmap(0, size, 3 /* RW */, 0x22 /* ANON */, -1, 0); struct host_timeval { int tv_sec; int tv_usec; }; int host_gettimeofday(struct host_timeval *a, void *b); int host_select(int nfds, long *readfds, long *writefds, long *exceptfds, struct host_timeval *timeout); -int kexec_load(vm_offset_t start); +int kexec_load(vm_offset_t start, int nsegs, void *segs); int host_reboot(int, int, int, void *); int host_getdents(int fd, void *dirp, int count); #endif Index: user/nwhitehorn/kboot/powerpc/kboot/kbootfdt.c =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/kbootfdt.c (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/kbootfdt.c (revision 276507) @@ -1,140 +1,121 @@ /*- * Copyright (C) 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 #include #include "bootstrap.h" #include "host_syscall.h" static void -print_fdt(void *fdtp) -{ - int offset, depth, i; - const char *compat; - - offset = fdt_path_offset(fdtp, "/"); - - for (depth = 0, offset = fdt_next_node(fdtp, offset, &depth); - offset >= 0; offset = fdt_next_node(fdtp, offset, &depth)) { - for (i = 1; i < depth; i++) printf("\t"); - printf("%d: %s",offset, fdt_get_name(fdtp, offset, NULL)); - compat = fdt_getprop(fdtp, offset, "compatible", NULL); - if (compat != NULL) - printf(" (%s)", compat); - printf("\n"); - } -} - -static void add_node_to_fdt(void *buffer, const char *path, int fdt_offset) { int child_offset, fd, pfd, error, dentsize; char subpath[512]; void *propbuf; ssize_t proplen; struct host_dent { unsigned long d_fileno; unsigned long d_off; unsigned short d_reclen; char d_name[]; /* uint8_t d_type; */ }; char dents[2048]; struct host_dent *dent; int d_type; - fd = open(path, O_RDONLY); + fd = host_open(path, O_RDONLY, 0); while (1) { dentsize = host_getdents(fd, dents, sizeof(dents)); if (dentsize <= 0) break; for (dent = (struct host_dent *)dents; (char *)dent < dents + dentsize; dent = (struct host_dent *)((void *)dent + dent->d_reclen)) { sprintf(subpath, "%s/%s", path, dent->d_name); if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; d_type = *((char *)(dent) + dent->d_reclen - 1); if (d_type == 4 /* DT_DIR */) { child_offset = fdt_add_subnode(buffer, fdt_offset, dent->d_name); if (child_offset < 0) { printf("Error %d adding node %s/%s, skipping\n", child_offset, path, dent->d_name); continue; } add_node_to_fdt(buffer, subpath, child_offset); } else { - pfd = open(subpath, O_RDONLY); propbuf = malloc(1024); - proplen = read(pfd, propbuf, 1024); - if (proplen < 0) - proplen = 0; + proplen = 0; + pfd = host_open(subpath, O_RDONLY, 0); + if (pfd > 0) { + proplen = host_read(pfd, propbuf, 1024); + host_close(pfd); + } error = fdt_setprop(buffer, fdt_offset, dent->d_name, propbuf, proplen); free(propbuf); - close(pfd); if (error) printf("Error %d adding property %s to " "node %d\n", error, dent->d_name, fdt_offset); } } } - close(fd); + host_close(fd); } int fdt_platform_load_dtb(void) { void *buffer; size_t buflen = 409600; char path[255] = "/proc/device-tree"; buffer = malloc(buflen); fdt_create_empty_tree(buffer, buflen); add_node_to_fdt(buffer, path, fdt_path_offset(buffer, "/")); fdt_pack(buffer); -printf("Device tree is %d total bytes\n", fdt_totalsize(buffer)); fdt_load_dtb_addr(buffer); return (0); } void fdt_platform_fixups(void) { } Index: user/nwhitehorn/kboot/powerpc/kboot/main.c =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/main.c (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/main.c (revision 276507) @@ -1,289 +1,306 @@ /*- * 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 +#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); +extern int command_fdt_internal(int argc, char *argv[]); + 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; } 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; const char *bootdev = argv[1]; /* * Set the heap to one page after the end of the loader. */ heapbase = host_getmem(heapsize); setheap(heapbase, heapbase + heapsize); /* * Set up console. */ cons_probe(); printf("Boot device: %s\n", bootdev); 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", bootdev, 1); setenv("loaddev", bootdev, 1); setenv("LINES", "24", 1); interact(NULL); /* doesn't return */ return (0); } void exit(int code) { /* XXX: host_exit */ } void delay(int usecs) { struct host_timeval tvi, tv; uint64_t ti, t; host_gettimeofday(&tvi, NULL); ti = tvi.tv_sec*1000000 + tvi.tv_usec; do { host_gettimeofday(&tv, NULL); t = tv.tv_sec*1000000 + tv.tv_usec; } while (t < ti + usecs); } int getsecs() { struct host_timeval tv; host_gettimeofday(&tv, NULL); return (tv.tv_sec); } 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; + int bufsz; void *mem; - size_t memsz; + int 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; - dest += 32*1024*1024; /* XXX Make nonoverlapping somehow */ 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) { 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) { 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); } 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; } kboot_copyin(buf, p, got); } free (buf); return (len - resid); } int kboot_autoload(void) { return (0); } void _start(int argc, const char **argv, char **env) { register volatile void **sp asm("r1"); main((int)sp[0], (const char **)&sp[1]); } + +/* + * Since proper fdt command handling function is defined in fdt_loader_cmd.c, + * and declaring it as extern is in contradiction with COMMAND_SET() macro + * (which uses static pointer), we're defining wrapper function, which + * calls the proper fdt handling routine. + */ +static int +command_fdt(int argc, char *argv[]) +{ + + return (command_fdt_internal(argc, argv)); +} + +COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt); Index: user/nwhitehorn/kboot/powerpc/kboot/metadata.c =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/metadata.c (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/metadata.c (revision 276507) @@ -1,342 +1,343 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include +#include #include #include "bootstrap.h" int md_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 =, with a single nul * separating each variable, and a double nul terminating the environment. */ vm_offset_t md_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); archsw.arch_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } archsw.arch_copyin("", addr, 1); addr++; } archsw.arch_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 */ static int align; #define COPY32(v, a, c) { \ u_int32_t x = (v); \ if (c) \ archsw.arch_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c) \ if (c) \ archsw.arch_copyin(s, a, strlen(s) + 1);\ a += roundup(strlen(s) + 1, align); \ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), align); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c);\ COPY32(mm->md_size, a, c); \ if (c) \ archsw.arch_copyin(mm->md_data, a, mm->md_size);\ a += roundup(mm->md_size, align); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } vm_offset_t md_copymodules(vm_offset_t addr, int kern64) { struct preloaded_file *fp; struct file_metadata *md; uint64_t scratch64; int c; c = addr != 0; /* 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, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); if (kern64) { scratch64 = fp->f_addr; MOD_ADDR(addr, scratch64, c); scratch64 = fp->f_size; MOD_SIZE(addr, scratch64, c); } else { MOD_ADDR(addr, fp->f_addr, c); MOD_SIZE(addr, fp->f_size, c); } for (md = fp->f_metadata; md != NULL; md = md->md_next) { if (!(md->md_type & MODINFOMD_NOCOPY)) { MOD_METADATA(addr, md, c); } } } MOD_END(addr, c); return(addr); } /* * Load the information expected by a powerpc kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) { struct preloaded_file *kfp; struct preloaded_file *xp; struct file_metadata *md; vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; vm_offset_t fdtp; vm_offset_t size; uint64_t scratch64; char *rootdevname; int howto; align = kern64 ? 8 : 4; howto = md_getboothowto(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"); if (rootdevname == NULL) rootdevname = getenv("currdev"); /* Try reading the /etc/fstab file to select the root device */ getrootmount(rootdevname); /* 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 = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = md_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* Copy out FDT */ size = fdt_copy(addr); *dtb = fdtp = addr; addr = roundup(addr + size, PAGE_SIZE); kernend = 0; kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) panic("can't find kernel file"); file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); if (kern64) { scratch64 = envp; file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); scratch64 = fdtp; file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64); scratch64 = kernend; file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64); } else { file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); } *modulep = addr; size = md_copymodules(0, kern64); kernend = roundup(addr + size, PAGE_SIZE); md = file_findmetadata(kfp, MODINFOMD_KERNEND); if (kern64) { scratch64 = kernend; bcopy(&scratch64, md->md_data, sizeof scratch64); } else { bcopy(&kernend, md->md_data, sizeof kernend); } (void)md_copymodules(addr, kern64); return(0); } int md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb) { return (md_load_dual(args, modulep, dtb, 0)); } int md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb) { return (md_load_dual(args, modulep, dtb, 1)); } Index: user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c =================================================================== --- user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c (revision 276506) +++ user/nwhitehorn/kboot/powerpc/kboot/ppc64_elf_freebsd.c (revision 276507) @@ -1,112 +1,114 @@ /*- * 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" #include "host_syscall.h" extern char end[]; extern vm_offset_t reloc; /* From /conf.c */ extern void *kerneltramp; extern size_t szkerneltramp; +extern int nkexec_segments; +extern void * loaded_segments; 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); return (0); } int ppc64_elf_exec(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp, dtb; Elf_Ehdr *e; int error; uint32_t *trampoline; - vm_offset_t trampolinebase = 32*1024*1024; /* XXX */ + vm_offset_t trampolinebase = 16*1024*1024; /* XXX */ if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; /* Handle function descriptor */ trampoline = malloc(szkerneltramp); memcpy(trampoline, &kerneltramp, szkerneltramp); trampoline[2] = e->e_entry; trampoline[4] = 0; /* Phys. mem offset */ trampoline[5] = 0; /* OF entry point */ if ((error = md_load64(fp->f_args, &mdp, &dtb)) != 0) return (error); trampoline[3] = dtb; trampoline[6] = mdp; trampoline[7] = sizeof(mdp); printf("Kernel entry at %#jx ...\n", e->e_entry); dev_cleanup(); archsw.arch_copyin(trampoline, trampolinebase, szkerneltramp); free(trampoline); - error = kexec_load(trampolinebase); + error = kexec_load(trampolinebase, nkexec_segments, &loaded_segments); if (error != 0) panic("kexec_load returned error: %d", error); error = host_reboot(0xfee1dead, 672274793, 0x45584543 /* LINUX_REBOOT_CMD_KEXEC */, NULL); if (error != 0) panic("reboot returned error: %d", error); while (1) {} panic("exec returned"); } struct file_format ppc_elf64 = { ppc64_elf_loadfile, ppc64_elf_exec };