diff --git a/stand/userboot/userboot/Makefile b/stand/userboot/userboot/Makefile index a1ba1b4d700e..2a66c0e3f8fe 100644 --- a/stand/userboot/userboot/Makefile +++ b/stand/userboot/userboot/Makefile @@ -1,65 +1,81 @@ LOADER_MSDOS_SUPPORT?= yes LOADER_UFS_SUPPORT?= yes LOADER_CD9660_SUPPORT?= no LOADER_EXT2FS_SUPPORT?= no PIC=yes # Note: -nostdlib needs to be added to LDFLAGS before including defs.mk LDFLAGS+= -nostdlib -Wl,-Bsymbolic .include SHLIB_NAME= userboot_${LOADER_INTERP}.so STRIP= LIBDIR= /boot +.if ${MACHINE_CPUARCH} == "amd64" +USERBOOT_KERNEL_SUPPORT= yes +.else +USERBOOT_KERNEL_SUPPORT= no +.endif + .PATH: ${.CURDIR}/../userboot SRCS= autoload.c SRCS+= bcache.c +.if ${MACHINE_CPUARCH} == "amd64" SRCS+= biossmap.c +.endif +.if ${USERBOOT_KERNEL_SUPPORT} == "yes" SRCS+= bootinfo.c SRCS+= bootinfo32.c SRCS+= bootinfo64.c +.endif SRCS+= conf.c SRCS+= copy.c SRCS+= devicename.c +.if ${USERBOOT_KERNEL_SUPPORT} == "yes" SRCS+= elf32_freebsd.c SRCS+= elf64_freebsd.c +.endif SRCS+= host.c SRCS+= main.c SRCS+= userboot_cons.c SRCS+= userboot_disk.c SRCS+= vers.c CFLAGS+= -Wall CFLAGS+= -I${BOOTSRC}/userboot .if ${MK_LOADER_ZFS} != "no" CFLAGS.main.c+= -I${BOOTSRC}/libsa/zfs CFLAGS.main.c+= -I${SYSDIR}/contrib/openzfs/include CFLAGS.main.c+= -I${SYSDIR}/contrib/openzfs/include/os/freebsd/zfs .endif CWARNFLAGS.main.c += -Wno-implicit-function-declaration NEWVERSWHAT= "User boot ${LOADER_INTERP}" ${MACHINE_CPUARCH} VERSION_FILE?= ${.CURDIR}/../userboot/version .if ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP} LINKS+= ${BINDIR}/${SHLIB_NAME} ${BINDIR}/userboot.so .endif +.if ${USERBOOT_KERNEL_SUPPORT} == "yes" +CFLAGS+= -DUSERBOOT_KERNEL_SUPPORT +.endif + .if ${MK_LOADER_ZFS} != "no" CFLAGS+= -DUSERBOOT_ZFS_SUPPORT HAVE_ZFS=yes .endif HELP_FILENAME= loader.help.userboot # Always add MI sources .include "${BOOTSRC}/loader.mk" CFLAGS+= -I. DPADD+= ${LDR_INTERP} ${LIBSA} LDADD+= ${LDR_INTERP} ${LIBSA} .include diff --git a/stand/userboot/userboot/conf.c b/stand/userboot/userboot/conf.c index abfd16c592e7..63f64cb97fbe 100644 --- a/stand/userboot/userboot/conf.c +++ b/stand/userboot/userboot/conf.c @@ -1,112 +1,116 @@ /*- * Copyright (c) 1997 * 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. * * $NetBSD: conf.c,v 1.2 1997/03/22 09:03:29 thorpej Exp $ */ #include #include "libuserboot.h" #if defined(USERBOOT_ZFS_SUPPORT) #include "libzfs.h" #endif extern struct devsw vdisk_dev; /* * We could use linker sets for some or all of these, but * then we would have to control what ended up linked into * the bootstrap. So it's easier to conditionalise things * here. * * XXX rename these arrays to be consistent and less namespace-hostile */ /* Exported for libsa */ struct devsw *devsw[] = { &host_dev, &userboot_disk, &vdisk_dev, #if defined(USERBOOT_ZFS_SUPPORT) &zfs_dev, #endif NULL }; struct fs_ops *file_system[] = { &host_fsops, &ufs_fsops, &cd9660_fsops, #if defined(USERBOOT_ZFS_SUPPORT) &zfs_fsops, #endif &gzipfs_fsops, &bzipfs_fsops, NULL }; /* to keep libsa happy */ struct netif_driver *netif_drivers[] = { NULL }; /* Exported for i386 only */ /* * Sort formats so that those that can detect based on arguments * rather than reading the file go first. */ +#if defined(__amd64__) extern struct file_format i386_elf; extern struct file_format i386_elf_obj; extern struct file_format amd64_elf; extern struct file_format amd64_elf_obj; +#endif struct file_format *file_formats[] = { +#if defined(__amd64__) &i386_elf, &i386_elf_obj, &amd64_elf, &amd64_elf_obj, +#endif NULL }; /* * Consoles * * We don't prototype these in libuserboot.h because they require * data structures from bootstrap.h as well. */ extern struct console userboot_console; extern struct console userboot_comconsole; struct console *consoles[] = { &userboot_console, &userboot_comconsole, NULL }; diff --git a/stand/userboot/userboot/main.c b/stand/userboot/userboot/main.c index 53b76c685d92..03f226c08bb9 100644 --- a/stand/userboot/userboot/main.c +++ b/stand/userboot/userboot/main.c @@ -1,323 +1,328 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 1998,2000 Doug Rabson * 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 #include #include #include #include "bootstrap.h" #include "disk.h" #include "libuserboot.h" #if defined(USERBOOT_ZFS_SUPPORT) #include #include "libzfs.h" static void userboot_zfs_probe(void); static int userboot_zfs_found; #endif /* Minimum version required */ #define USERBOOT_VERSION USERBOOT_VERSION_3 #define LOADER_PATH "/boot/loader" #define INTERP_MARKER "$Interpreter:" #define MALLOCSZ (64*1024*1024) struct loader_callbacks *callbacks; void *callbacks_arg; static jmp_buf jb; struct arch_switch archsw = { /* MI/MD interface boundary */ .arch_autoload = userboot_autoload, .arch_getdev = userboot_getdev, .arch_copyin = userboot_copyin, .arch_copyout = userboot_copyout, .arch_readin = userboot_readin, #if defined(USERBOOT_ZFS_SUPPORT) .arch_zfs_probe = userboot_zfs_probe, #endif }; static void extract_currdev(void); static void check_interpreter(void); void delay(int usec) { CALLBACK(delay, usec); } time_t getsecs(void) { /* * userboot can't do netboot, so this implementation isn't strictly * required. Defining it avoids issues with BIND_NOW, and it doesn't * hurt to do it. */ return (time(NULL)); } void exit(int v) { CALLBACK(exit, v); longjmp(jb, 1); } static void check_interpreter(void) { struct stat st; size_t marklen, rdsize; const char *guest_interp, *my_interp; char *buf; int fd; /* * If we can't stat(2) or open(2) LOADER_PATH, then we'll fail by * simply letting us roll on with whatever interpreter we were compiled * with. This is likely not going to be an issue in reality. */ buf = NULL; if (stat(LOADER_PATH, &st) != 0) return; if ((fd = open(LOADER_PATH, O_RDONLY)) < 0) return; rdsize = st.st_size; buf = malloc(rdsize); if (buf == NULL) goto out; if (read(fd, buf, rdsize) < rdsize) goto out; marklen = strlen(INTERP_MARKER); my_interp = bootprog_interp + marklen; /* * Here we make the assumption that a loader binary without the * interpreter marker is a 4th one. All loader binaries going forward * should have this properly specified, so our assumption should always * be a good one. */ if ((guest_interp = memmem(buf, rdsize, INTERP_MARKER, marklen)) != NULL) guest_interp += marklen; else guest_interp = "4th"; /* * The guest interpreter may not have a version of loader that * specifies the interpreter installed. If that's the case, we'll * assume it's legacy (4th) and request a swap to that if we're * a Lua-userboot. */ if (strcmp(my_interp, guest_interp) != 0) CALLBACK(swap_interpreter, guest_interp); out: free(buf); close(fd); return; } void loader_main(struct loader_callbacks *cb, void *arg, int version, int ndisks) { static char mallocbuf[MALLOCSZ]; char *var; int i; if (version < USERBOOT_VERSION) abort(); callbacks = cb; callbacks_arg = arg; userboot_disk_maxunit = ndisks; /* * initialise the heap as early as possible. Once this is done, * alloc() is usable. */ setheap((void *)mallocbuf, (void *)(mallocbuf + sizeof(mallocbuf))); /* * Hook up the console */ cons_probe(); /* Set up currdev variable to have hooks in place. */ env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset); printf("\n%s", bootprog_info); #if 0 printf("Memory: %ld k\n", memsize() / 1024); #endif setenv("LINES", "24", 1); /* optional */ /* * Set custom environment variables */ i = 0; while (1) { var = CALLBACK(getenv, i++); if (var == NULL) break; putenv(var); } /* * Initialise the block cache. Set the upper limit. */ bcache_init(32768, 512); devinit(); extract_currdev(); +#if !defined(USERBOOT_KERNEL_SUPPORT) + printf("WARNING: This userboot does not support loading a kernel\n"); + delay(1500000); +#endif + /* * Checking the interpreter isn't worth the overhead unless we * actually have the swap_interpreter callback, so we actually version * check here rather than later on. */ if (version >= USERBOOT_VERSION_5) check_interpreter(); if (setjmp(jb)) return; interact(); /* doesn't return */ exit(0); } /* * Set the 'current device' by (if possible) recovering the boot device as * supplied by the initial bootstrap. */ static void extract_currdev(void) { struct disk_devdesc dev; struct devdesc *dd; #if defined(USERBOOT_ZFS_SUPPORT) struct zfs_devdesc zdev; if (userboot_zfs_found) { /* Leave the pool/root guid's unassigned */ bzero(&zdev, sizeof(zdev)); zdev.dd.d_dev = &zfs_dev; init_zfs_boot_options(devformat(&zdev.dd)); dd = &zdev.dd; } else #endif if (userboot_disk_maxunit > 0) { dev.dd.d_dev = &userboot_disk; dev.dd.d_unit = 0; dev.d_slice = D_SLICEWILD; dev.d_partition = D_PARTWILD; /* * If we cannot auto-detect the partition type then * access the disk as a raw device. */ if (dev.dd.d_dev->dv_open(NULL, &dev)) { dev.d_slice = D_SLICENONE; dev.d_partition = D_PARTNONE; } dd = &dev.dd; } else { dev.dd.d_dev = &host_dev; dev.dd.d_unit = 0; dd = &dev.dd; } set_currdev(devformat(dd)); #if defined(USERBOOT_ZFS_SUPPORT) if (userboot_zfs_found) { char buf[VDEV_PAD_SIZE]; if (zfs_get_bootonce(&zdev, OS_BOOTONCE, buf, sizeof(buf)) == 0) { printf("zfs bootonce: %s\n", buf); set_currdev(buf); setenv("zfs-bootonce", buf, 1); } (void)zfs_attach_nvstore(&zdev); } #endif } #if defined(USERBOOT_ZFS_SUPPORT) static void userboot_zfs_probe(void) { char devname[32]; uint64_t pool_guid; int unit; /* * Open all the disks we can find and see if we can reconstruct * ZFS pools from them. Record if any were found. */ for (unit = 0; unit < userboot_disk_maxunit; unit++) { sprintf(devname, "disk%d:", unit); pool_guid = 0; zfs_probe_dev(devname, &pool_guid, true); if (pool_guid != 0) userboot_zfs_found = 1; } } #endif COMMAND_SET(quit, "quit", "exit the loader", command_quit); static int command_quit(int argc, char *argv[]) { exit(USERBOOT_EXIT_QUIT); return (CMD_OK); } COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int command_reboot(int argc, char *argv[]) { exit(USERBOOT_EXIT_REBOOT); return (CMD_OK); }