From owner-svn-src-all@freebsd.org Thu Feb 21 03:18:18 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id F1BB314ECA1C; Thu, 21 Feb 2019 03:18:17 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 9E8868743F; Thu, 21 Feb 2019 03:18:17 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8E027F7C6; Thu, 21 Feb 2019 03:18:17 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x1L3IHjm002956; Thu, 21 Feb 2019 03:18:17 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x1L3IDMI002935; Thu, 21 Feb 2019 03:18:13 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201902210318.x1L3IDMI002935@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Thu, 21 Feb 2019 03:18:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r344413 - in stable/11: release/tools share/mk stand stand/common stand/efi stand/efi/loader stand/efi/loader_4th stand/efi/loader_lua stand/efi/loader_simp stand/i386 stand/i386/loader... X-SVN-Group: stable-11 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable/11: release/tools share/mk stand stand/common stand/efi stand/efi/loader stand/efi/loader_4th stand/efi/loader_lua stand/efi/loader_simp stand/i386 stand/i386/loader stand/i386/loader_4th st... X-SVN-Commit-Revision: 344413 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 9E8868743F X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.96 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_LONG(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.96)[-0.961,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 Feb 2019 03:18:18 -0000 Author: kevans Date: Thu Feb 21 03:18:12 2019 New Revision: 344413 URL: https://svnweb.freebsd.org/changeset/base/344413 Log: MFC Loader Interpreter Coexistance: r337806, r337868, r337914, r337927, r337989, r338052, r338064, r338407, r338418, r338474 r337806: Create a loader for each interpreter for x86 BIOS and all EFI Create loader_{4th,lua,simp}{,.efi}. All of these are installed by default. Create LOADER_DEFAULT_INTERP to specify the default interpreter when no other is specified. LOADER_INTERP is the current interpreter language building. Turn building of lua on by default to match 4th. simploader is a simplified loader build w/o any interpreter language (but with a simple loader). This is the historic behavir you got with WITHOUT_FORTH. Make a hard link to the default loader. This has to be a hard link rather than the more desirable soft link because older zfsboot blocks don't support symlinks. r337868: stand: Use -Oz/-Os for all loader/stand builds. While we're not super size constrained, the x86 BIOS /boot/loader has to be less than about 520k-530k to be reliable. The LUA loader is at this size today. -Oz saves 15-20% on the size, keeping us safely small enough (comparable to where we were with the 4th loader). This will also help with sjg's work on bringing in bearssl, though we may again be looking for space in the LUA loader. Size table for clang 6.0.0: default -O1 -Os -Oz 4th 442368 417792 389120 376832 lua 524288 479232 446464 430080 r337914: Install links for loader.efi. r337927: Add ashldi3 and ashrdi3 to mips. Now that we're using -Os, mips needs these routines. r337989: Copy the boot loader from the new location for the co-existing loaders. r338052: libsa: Add lshrdi3.c for powerpc* and mips r338064: Turn back the clock just a little: make userboot.so always be 4th Turns out there was a hidden dependency we hasn't counted upon. The host load /boot/userboot.so to boot the VMs it runs. This means that the change to lua meant suddently that nobody could run their older VMs because LUA wasn't in 10.0, last month's HardenedBSD, 11.2 or whatever. Even more than for the /boot/loader* binaries, we need a good coexistance strategy for this. While that's being designed and implemented, drop back to always 4th for userboot.so. This will fail safe in all but the most extreme environments (but lua-only hacks to .lua files won't be processes in VMs until we fix it). r338407: lualoader: Print error messages from command failures at the prompt Previously lualoader would remain silent, rather than printing command_errmsg or noting that a command had failed or was not found. r338418: userboot: handle guest interpreter mismatches more intelligently The switch to lualoader creates a problem with userboot: the host is inclined to build userboot with Lua, but the host userboot's interpreter must match what's available on the guest. For almost all FreeBSD guests in the wild, Lua is not yet available and a Lua-based userboot will fail. This revision updates userboot protocol to version 5, which adds a swap_interpreter callback to request a different interpreter, and tries to determine the proper interpreter to be used based on how the guest /boot/loader is compiled. This is still a bit of a guess, but it's likely the best possible guess we can make in order to get it right. The interpreter is now embedded in the resulting executable, so we can open /boot/loader on the guest and hunt that down to derive the interpreter it was built with. Using -l with bhyveload will not allow an intepreter swap, even if the loader specified happens to be a userboot with the wrong interpreter. We'll simply complain about the mismatch and bail out. For legacy guests without the interpreter marker, we assume they're 4th. For new guests with the interpreter marker, we'll read it and swap over to the proper interpreter if it doesn't match what the userboot we're using was compiled with. Both flavors of userboot are installed by default, userboot_4th.so and userboot_lua.so. This fixes the build WITHOUT_FORTH as a coincidence, which was broken by userboot being forced to 4th. r338474: Be a little conservative about when to force size optimizations. Reports have come in that there's issue with powerpc and sparc64 since we've switched to using -Oz / -Os. We don't strictly need them for !x86, so be conservative about when we enable them. Added: stable/11/stand/efi/loader_4th/ - copied from r337806, head/stand/efi/loader_4th/ stable/11/stand/efi/loader_lua/ - copied from r337806, head/stand/efi/loader_lua/ stable/11/stand/efi/loader_simp/ - copied from r337806, head/stand/efi/loader_simp/ stable/11/stand/i386/loader_4th/ - copied from r337806, head/stand/i386/loader_4th/ stable/11/stand/i386/loader_lua/ - copied from r337806, head/stand/i386/loader_lua/ stable/11/stand/i386/loader_simp/ - copied from r337806, head/stand/i386/loader_simp/ stable/11/stand/userboot/userboot_4th/ - copied from r338418, head/stand/userboot/userboot_4th/ stable/11/stand/userboot/userboot_lua/ - copied from r338418, head/stand/userboot/userboot_lua/ Modified: stable/11/release/tools/arm.subr stable/11/share/mk/src.opts.mk stable/11/stand/common/bootstrap.h stable/11/stand/common/interp_forth.c stable/11/stand/common/interp_lua.c stable/11/stand/common/interp_simple.c stable/11/stand/defs.mk stable/11/stand/efi/Makefile stable/11/stand/efi/loader/Makefile stable/11/stand/i386/Makefile stable/11/stand/i386/loader/Makefile stable/11/stand/i386/pxeldr/Makefile stable/11/stand/libsa/Makefile stable/11/stand/loader.mk stable/11/stand/userboot/Makefile stable/11/stand/userboot/userboot.h stable/11/stand/userboot/userboot/Makefile stable/11/stand/userboot/userboot/main.c stable/11/stand/userboot/userboot/version stable/11/usr.sbin/bhyveload/bhyveload.c Directory Properties: stable/11/ (props changed) Modified: stable/11/release/tools/arm.subr ============================================================================== --- stable/11/release/tools/arm.subr Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/release/tools/arm.subr Thu Feb 21 03:18:12 2019 (r344413) @@ -152,7 +152,7 @@ arm_install_boot() { BOOTFILES="$(chroot ${CHROOTDIR} realpath ${BOOTFILES})" chroot ${CHROOTDIR} mkdir -p ${FATMOUNT}/EFI/BOOT - chroot ${CHROOTDIR} cp -p ${BOOTFILES}/efi/loader/loader.efi \ + chroot ${CHROOTDIR} cp -p ${BOOTFILES}/efi/loader_lua/loader_lua.efi \ ${FATMOUNT}/EFI/BOOT/$(efi_boot_name ${EMBEDDED_TARGET}) chroot ${CHROOTDIR} touch ${UFSMOUNT}/firstboot Modified: stable/11/share/mk/src.opts.mk ============================================================================== --- stable/11/share/mk/src.opts.mk Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/share/mk/src.opts.mk Thu Feb 21 03:18:12 2019 (r344413) @@ -126,6 +126,7 @@ __DEFAULT_YES_OPTIONS = \ LIBPTHREAD \ LIBTHR \ LOADER_GELI \ + LOADER_LUA \ LOADER_OFW \ LOADER_UBOOT \ LOCALES \ @@ -196,7 +197,6 @@ __DEFAULT_NO_OPTIONS = \ LINT \ LOADER_FIREWIRE \ LOADER_FORCE_LE \ - LOADER_LUA \ NAND \ OFED_EXTRA \ OPENLDAP \ Modified: stable/11/stand/common/bootstrap.h ============================================================================== --- stable/11/stand/common/bootstrap.h Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/common/bootstrap.h Thu Feb 21 03:18:12 2019 (r344413) @@ -164,6 +164,14 @@ extern int isapnp_readport; extern char bootprog_info[]; /* + * Interpreter information + */ +extern const char bootprog_interp[]; +#define INTERP_DEFINE(interpstr) \ +const char bootprog_interp[] = "$Interpreter:" interpstr + + +/* * Preloaded file metadata header. * * Metadata are allocated on our heap, and copied into kernel space Modified: stable/11/stand/common/interp_forth.c ============================================================================== --- stable/11/stand/common/interp_forth.c Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/common/interp_forth.c Thu Feb 21 03:18:12 2019 (r344413) @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include "ficl.h" extern unsigned bootprog_rev; +INTERP_DEFINE("4th"); /* #define BFORTH_DEBUG */ Modified: stable/11/stand/common/interp_lua.c ============================================================================== --- stable/11/stand/common/interp_lua.c Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/common/interp_lua.c Thu Feb 21 03:18:12 2019 (r344413) @@ -60,6 +60,7 @@ static struct interp_lua_softc lua_softc; #define LDBG(...) #endif +INTERP_DEFINE("lua"); static void * interp_lua_realloc(void *ud __unused, void *ptr, size_t osize __unused, size_t nsize) @@ -135,7 +136,7 @@ interp_run(const char *line) char **argv; lua_State *luap; struct interp_lua_softc *softc = &lua_softc; - int status; + int status, ret; luap = softc->luap; LDBG("executing line..."); @@ -147,14 +148,16 @@ interp_run(const char *line) * run it through cli_execute. If that fails, then we'll try it * as a builtin. */ + command_errmsg = NULL; if (parse(&argc, &argv, line) == 0) { lua_getglobal(luap, "cli_execute"); for (nargc = 0; nargc < argc; ++nargc) { lua_pushstring(luap, argv[nargc]); } status = lua_pcall(luap, argc, 1, 0); + ret = lua_tointeger(luap, 1); lua_pop(luap, 1); - if (status != 0) { + if (status != 0 || ret != 0) { /* * Lua cli_execute will pass the function back * through loader.command, which is a proxy to @@ -166,7 +169,10 @@ interp_run(const char *line) status = interp_builtin_cmd(argc, argv); } if (status != 0) { - printf("Command failed\n"); + if (command_errmsg != NULL) + printf("%s\n", command_errmsg); + else + printf("Command failed\n"); status = CMD_ERROR; } free(argv); Modified: stable/11/stand/common/interp_simple.c ============================================================================== --- stable/11/stand/common/interp_simple.c Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/common/interp_simple.c Thu Feb 21 03:18:12 2019 (r344413) @@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$"); #include #include "bootstrap.h" +INTERP_DEFINE("simp"); + void interp_init(void) { Modified: stable/11/stand/defs.mk ============================================================================== --- stable/11/stand/defs.mk Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/defs.mk Thu Feb 21 03:18:12 2019 (r344413) @@ -53,8 +53,15 @@ CFLAGS+= -I${SASRC} -D_STANDALONE CFLAGS+= -I${SYSDIR} # Spike the floating point interfaces CFLAGS+= -Ddouble=jagged-little-pill -Dfloat=floaty-mcfloatface +.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" +# Slim down the image. This saves about 15% in size with clang 6 on x86 +# Our most constrained /boot/loader env is BIOS booting on x86, where +# our text + data + BTX have to fit into 640k below the ISA hole. +# Experience has shown that problems arise between ~520k to ~530k. +CFLAGS.clang+= -Oz +CFLAGS.gcc+= -Os +.endif - # GELI Support, with backward compat hooks (mostly) .if defined(LOADER_NO_GELI_SUPPORT) MK_LOADER_GELI=no @@ -145,6 +152,18 @@ CFLAGS+= -G0 -fno-pic -mno-abicalls CFLAGS+= -mlittle-endian .endif .endif + +# +# Have a sensible default +# +.if ${MK_FORTH} == "yes" +LOADER_DEFAULT_INTERP?=4th +.elif ${MK_LOADER_LUA} == "yes" +LOADER_DEFAULT_INTERP?=lua +.else +LOADER_DEFAULT_INTERP?=simp +.endif +LOADER_INTERP?=${LOADER_DEFAULT_INTERP} # Make sure we use the machine link we're about to create CFLAGS+=-I. Modified: stable/11/stand/efi/Makefile ============================================================================== --- stable/11/stand/efi/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/efi/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -9,7 +9,10 @@ NO_OBJ=t .if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500 SUBDIR.${MK_FDT}+= fdt -SUBDIR.yes+= libefi loader boot1 +SUBDIR.yes+= libefi boot1 +SUBDIR.${MK_FORTH}+= loader_4th +SUBDIR.${MK_LOADER_LUA}+= loader_lua +SUBDIR.yes+= loader_simp .endif # ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 40500 Modified: stable/11/stand/efi/loader/Makefile ============================================================================== --- stable/11/stand/efi/loader/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/efi/loader/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -8,7 +8,8 @@ LOADER_EXT2FS_SUPPORT?= no .include -PROG= loader.sym +LOADER?= loader_${LOADER_INTERP} +PROG= ${LOADER}.sym INTERNALPROG= WARNS?= 3 @@ -24,6 +25,7 @@ SRCS= autoload.c \ smbios.c \ vers.c +CFLAGS+= -I${.CURDIR}/../loader .if ${MK_LOADER_ZFS} != "no" CFLAGS+= -I${ZFSSRC} CFLAGS+= -DEFI_ZFS_BOOT @@ -41,10 +43,11 @@ CWARNFLAGS.self_reloc.c+= -Wno-error=maybe-uninitializ # warnings for now. CWARNFLAGS.main.c+= -Wno-format -.PATH: ${.CURDIR}/arch/${MACHINE} -# For smbios.c +.PATH: ${.CURDIR}/../loader +.PATH: ${.CURDIR}/../loader/arch/${MACHINE} +# For smbios.c XXX need to abstract properly .PATH: ${BOOTSRC}/i386/libi386 -.include "${.CURDIR}/arch/${MACHINE}/Makefile.inc" +.include "${.CURDIR}/../loader/arch/${MACHINE}/Makefile.inc" CFLAGS+= -I${.CURDIR} CFLAGS+= -I${.CURDIR}/arch/${MACHINE} @@ -78,20 +81,25 @@ HAVE_BCACHE= yes CFLAGS+= -DEFI_STAGING_SIZE=${EFI_STAGING_SIZE} .endif +NEWVERSWHAT= "EFI loader" ${MACHINE} +VERSION_FILE= ${.CURDIR}/../loader/version + # Always add MI sources .include "${BOOTSRC}/loader.mk" -FILES+= loader.efi -FILESMODE_loader.efi= ${BINMODE} +FILES+= ${LOADER}.efi +FILESMODE_${LOADER}.efi= ${BINMODE} -LDSCRIPT= ${.CURDIR}/arch/${MACHINE}/ldscript.${MACHINE} +.if ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP} +LINKS+= ${BINDIR}/${LOADER}.efi ${BINDIR}/loader.efi +.endif + +LDSCRIPT= ${.CURDIR}/../loader/arch/${MACHINE}/ldscript.${MACHINE} LDFLAGS+= -Wl,-T${LDSCRIPT},-Bsymbolic,-znotext -shared CLEANFILES+= loader.efi -NEWVERSWHAT= "EFI loader" ${MACHINE} - -loader.efi: ${PROG} +${LOADER}.efi: ${PROG} if ${NM} ${.ALLSRC} | grep ' U '; then \ echo "Undefined symbols in ${.ALLSRC}"; \ exit 1; \ Modified: stable/11/stand/i386/Makefile ============================================================================== --- stable/11/stand/i386/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/i386/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -9,7 +9,9 @@ SUBDIR.yes= mbr pmbr boot0 boot0sio btx boot2 cdboot g SUBDIR.${MK_LOADER_FIREWIRE}+= libfirewire -SUBDIR.yes+= loader +SUBDIR.${MK_FORTH}+= loader_4th +SUBDIR.${MK_LOADER_LUA}+= loader_lua +SUBDIR.yes+= loader_simp # special boot programs, 'self-extracting boot2+loader' SUBDIR.yes+= pxeldr Modified: stable/11/stand/i386/loader/Makefile ============================================================================== --- stable/11/stand/i386/loader/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/i386/loader/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -14,7 +14,7 @@ LOADER_BZIP2_SUPPORT?= yes .include -LOADER?= loader +LOADER?= loader_${LOADER_INTERP} PROG= ${LOADER}.sym INTERNALPROG= NEWVERSWHAT?= "bootstrap loader" x86 @@ -64,12 +64,13 @@ ${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN} ${LOADER}.bin: ${LOADER}.sym strip -R .comment -R .note -o ${.TARGET} ${.ALLSRC} -# XXX TODO: Fix this when coexistence comes in -.if ${MK_LOADER_ZFS} == "yes" # && ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP} +.if ${MK_LOADER_ZFS} == "yes" && ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP} LINKS+= ${BINDIR}/${LOADER} ${BINDIR}/zfsloader .endif +.if ${LOADER_INTERP} == ${LOADER_DEFAULT_INTERP} +LINKS+= ${BINDIR}/${LOADER} ${BINDIR}/loader +.endif FILES+= ${LOADER} -# XXX INSTALLFLAGS_loader= -b FILESMODE_${LOADER}= ${BINMODE} -b # XXX crt0.o needs to be first for pxeboot(8) to work Modified: stable/11/stand/i386/pxeldr/Makefile ============================================================================== --- stable/11/stand/i386/pxeldr/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/i386/pxeldr/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -24,7 +24,8 @@ CFLAGS+=-DALWAYS_SERIAL CFLAGS+=-I${BOOTSRC}/i386/common -LOADERBIN= ${BOOTOBJ}/i386/loader/loader.bin +L=${LOADER_DEFAULT_INTERP} +LOADERBIN= ${BOOTOBJ}/i386/loader_${L}/loader_${L}.bin CLEANFILES+= ${BOOT}.tmp Modified: stable/11/stand/libsa/Makefile ============================================================================== --- stable/11/stand/libsa/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/libsa/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -73,8 +73,13 @@ SRCS+= aeabi_memcmp.S aeabi_memcpy.S aeabi_memmove.S a .if ${MACHINE_CPUARCH} == "powerpc" .PATH: ${LIBC_SRC}/quad -SRCS+= ashldi3.c ashrdi3.c +SRCS+= ashldi3.c ashrdi3.c lshrdi3.c SRCS+= syncicache.c +.endif + +.if ${MACHINE_CPUARCH} == "mips" +.PATH: ${LIBC_SRC}/quad +SRCS+= ashldi3.c ashrdi3.c lshrdi3.c .endif # uuid functions from libc Modified: stable/11/stand/loader.mk ============================================================================== --- stable/11/stand/loader.mk Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/loader.mk Thu Feb 21 03:18:12 2019 (r344413) @@ -59,19 +59,20 @@ SRCS+= isapnp.c SRCS+= pnp.c .endif -# Forth interpreter -.if ${MK_FORTH} != "no" -SRCS+= interp_forth.c -.include "${BOOTSRC}/ficl.mk" -LDR_INTERP= ${LIBFICL} -LDR_INTERP32= ${LIBFICL32} -.elif ${MK_LOADER_LUA} != "no" +.if ${LOADER_INTERP} == "lua" SRCS+= interp_lua.c .include "${BOOTSRC}/lua.mk" LDR_INTERP= ${LIBLUA} LDR_INTERP32= ${LIBLUA32} -.else +.elif ${LOADER_INTERP} == "4th" +SRCS+= interp_forth.c +.include "${BOOTSRC}/ficl.mk" +LDR_INTERP= ${LIBFICL} +LDR_INTERP32= ${LIBFICL32} +.elif ${LOADER_INTERP} == "simp" SRCS+= interp_simple.c +.else +.error Unknown interpreter ${LOADER_INTERP} .endif .if defined(BOOT_PROMPT_123) Modified: stable/11/stand/userboot/Makefile ============================================================================== --- stable/11/stand/userboot/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/userboot/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -1,8 +1,10 @@ # $FreeBSD$ -.include +.include -SUBDIR= test userboot +SUBDIR.yes= test +SUBDIR.${MK_FORTH}+= userboot_4th +SUBDIR.${MK_LOADER_LUA}+= userboot_lua .include Modified: stable/11/stand/userboot/userboot.h ============================================================================== --- stable/11/stand/userboot/userboot.h Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/userboot/userboot.h Thu Feb 21 03:18:12 2019 (r344413) @@ -42,6 +42,13 @@ #define USERBOOT_VERSION_4 4 /* + * Version 5 added a callback for indicating that the guest + * should be restarted with a different interpreter. The callback + * structure is still backward compatible. + */ +#define USERBOOT_VERSION_5 5 + +/* * Exit codes from the loader */ #define USERBOOT_EXIT_QUIT 1 @@ -210,4 +217,9 @@ struct loader_callbacks { int (*vm_set_register)(void *arg, int vcpu, int reg, uint64_t val); int (*vm_set_desc)(void *arg, int vcpu, int reg, uint64_t base, u_int limit, u_int access); + + /* + * Version 5 addition. + */ + void (*swap_interpreter)(void *arg, const char *interp); }; Modified: stable/11/stand/userboot/userboot/Makefile ============================================================================== --- stable/11/stand/userboot/userboot/Makefile Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/userboot/userboot/Makefile Thu Feb 21 03:18:12 2019 (r344413) @@ -8,10 +8,11 @@ PIC=yes .include -SHLIB_NAME= userboot.so +SHLIB_NAME= userboot_${LOADER_INTERP}.so STRIP= LIBDIR= /boot +.PATH: ${.CURDIR}/../userboot SRCS= autoload.c SRCS+= bcache.c SRCS+= biossmap.c @@ -37,7 +38,12 @@ CWARNFLAGS.main.c += -Wno-implicit-function-declaratio LDFLAGS+= -nostdlib -Wl,-Bsymbolic -NEWVERSWHAT= "User boot" ${MACHINE_CPUARCH} +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 ${MK_LOADER_ZFS} != "no" CFLAGS+= -DUSERBOOT_ZFS_SUPPORT Modified: stable/11/stand/userboot/userboot/main.c ============================================================================== --- stable/11/stand/userboot/userboot/main.c Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/userboot/userboot/main.c Thu Feb 21 03:18:12 2019 (r344413) @@ -47,6 +47,9 @@ static int userboot_zfs_found; /* 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; @@ -57,6 +60,7 @@ static jmp_buf jb; struct arch_switch archsw; /* MI/MD interface boundary */ static void extract_currdev(void); +static void check_interpreter(void); void delay(int usec) @@ -73,6 +77,62 @@ exit(int 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) { @@ -137,6 +197,14 @@ loader_main(struct loader_callbacks *cb, void *arg, in (devsw[i]->dv_init)(); extract_currdev(); + + /* + * 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; Modified: stable/11/stand/userboot/userboot/version ============================================================================== --- stable/11/stand/userboot/userboot/version Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/stand/userboot/userboot/version Thu Feb 21 03:18:12 2019 (r344413) @@ -1,4 +1,5 @@ $FreeBSD$ +1.2: Userboot with lua or forth 1.1: Initial userland boot Modified: stable/11/usr.sbin/bhyveload/bhyveload.c ============================================================================== --- stable/11/usr.sbin/bhyveload/bhyveload.c Thu Feb 21 02:52:27 2019 (r344412) +++ stable/11/usr.sbin/bhyveload/bhyveload.c Thu Feb 21 03:18:12 2019 (r344413) @@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -98,6 +99,13 @@ static int disk_fd[NDISKS]; static int ndisks; static int consin_fd, consout_fd; +static int need_reinit; + +static void *loader_hdl; +static char *loader; +static int explicit_loader; +static jmp_buf jb; + static char *vmname, *progname; static struct vmctx *ctx; @@ -560,6 +568,30 @@ cb_vm_set_desc(void *arg, int vcpu, int reg, uint64_t return (vm_set_desc(ctx, vcpu, reg, base, limit, access)); } +static void +cb_swap_interpreter(void *arg, const char *interp_req) +{ + + /* + * If the user specified a loader but we detected a mismatch, we should + * not try to pivot to a different loader on them. + */ + free(loader); + if (explicit_loader == 1) { + perror("requested loader interpreter does not match guest userboot"); + cb_exit(NULL, 1); + } + if (interp_req == NULL || *interp_req == '\0') { + perror("guest failed to request an interpreter"); + cb_exit(NULL, 1); + } + + if (asprintf(&loader, "/boot/userboot_%s.so", interp_req) == -1) + err(EX_OSERR, "malloc"); + need_reinit = 1; + longjmp(jb, 1); +} + static struct loader_callbacks cb = { .getc = cb_getc, .putc = cb_putc, @@ -593,6 +625,9 @@ static struct loader_callbacks cb = { /* Version 4 additions */ .vm_set_register = cb_vm_set_register, .vm_set_desc = cb_vm_set_desc, + + /* Version 5 additions */ + .swap_interpreter = cb_swap_interpreter, }; static int @@ -661,16 +696,12 @@ usage(void) int main(int argc, char** argv) { - char *loader; - void *h; void (*func)(struct loader_callbacks *, void *, int, int); uint64_t mem_size; - int opt, error, need_reinit, memflags; + int opt, error, memflags; progname = basename(argv[0]); - loader = NULL; - memflags = 0; mem_size = 256 * MB; @@ -705,6 +736,7 @@ main(int argc, char** argv) loader = strdup(optarg); if (loader == NULL) err(EX_OSERR, "malloc"); + explicit_loader = 1; break; case 'm': @@ -747,6 +779,13 @@ main(int argc, char** argv) exit(1); } + /* + * setjmp in the case the guest wants to swap out interpreter, + * cb_swap_interpreter will swap out loader as appropriate and set + * need_reinit so that we end up in a clean state once again. + */ + setjmp(jb); + if (need_reinit) { error = vm_reinit(ctx); if (error) { @@ -767,13 +806,15 @@ main(int argc, char** argv) if (loader == NULL) err(EX_OSERR, "malloc"); } - h = dlopen(loader, RTLD_LOCAL); - if (!h) { + if (loader_hdl != NULL) + dlclose(loader_hdl); + loader_hdl = dlopen(loader, RTLD_LOCAL); + if (!loader_hdl) { printf("%s\n", dlerror()); free(loader); return (1); } - func = dlsym(h, "loader_main"); + func = dlsym(loader_hdl, "loader_main"); if (!func) { printf("%s\n", dlerror()); free(loader); @@ -790,7 +831,7 @@ main(int argc, char** argv) addenv("smbios.bios.vendor=BHYVE"); addenv("boot_serial=1"); - func(&cb, NULL, USERBOOT_VERSION_4, ndisks); + func(&cb, NULL, USERBOOT_VERSION_5, ndisks); free(loader); return (0);