Page MenuHomeFreeBSD

D16945.id47533.diff
No OneTemporary

D16945.id47533.diff

Index: stand/common/bootstrap.h
===================================================================
--- stand/common/bootstrap.h
+++ stand/common/bootstrap.h
@@ -163,6 +163,14 @@
*/
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.
*
Index: stand/common/interp_forth.c
===================================================================
--- stand/common/interp_forth.c
+++ stand/common/interp_forth.c
@@ -34,6 +34,7 @@
#include "ficl.h"
extern unsigned bootprog_rev;
+INTERP_DEFINE("4th");
/* #define BFORTH_DEBUG */
Index: stand/common/interp_lua.c
===================================================================
--- stand/common/interp_lua.c
+++ stand/common/interp_lua.c
@@ -60,6 +60,7 @@
#define LDBG(...)
#endif
+INTERP_DEFINE("lua");
static void *
interp_lua_realloc(void *ud __unused, void *ptr, size_t osize __unused, size_t nsize)
Index: stand/common/interp_simple.c
===================================================================
--- stand/common/interp_simple.c
+++ stand/common/interp_simple.c
@@ -35,6 +35,8 @@
#include <string.h>
#include "bootstrap.h"
+INTERP_DEFINE("simp");
+
void
interp_init(void)
{
Index: stand/userboot/Makefile
===================================================================
--- stand/userboot/Makefile
+++ stand/userboot/Makefile
@@ -1,8 +1,10 @@
# $FreeBSD$
-.include <bsd.own.mk>
+.include <bsd.init.mk>
-SUBDIR= test userboot
+SUBDIR.yes= test
+SUBDIR.${MK_FORTH}+= userboot_4th
+SUBDIR.${MK_LOADER_LUA}+= userboot_lua
.include <bsd.subdir.mk>
Index: stand/userboot/userboot.h
===================================================================
--- stand/userboot/userboot.h
+++ stand/userboot/userboot.h
@@ -41,6 +41,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
*/
@@ -210,4 +217,9 @@
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);
};
Index: stand/userboot/userboot/Makefile
===================================================================
--- stand/userboot/userboot/Makefile
+++ stand/userboot/userboot/Makefile
@@ -5,14 +5,14 @@
LOADER_CD9660_SUPPORT?= no
LOADER_EXT2FS_SUPPORT?= no
PIC=yes
-LOADER_INTERP=4th
.include <bsd.init.mk>
-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
@@ -33,12 +33,18 @@
CFLAGS+= -Wall
CFLAGS+= -I${BOOTSRC}/userboot
+CFLAGS+= -DLOADER_INTERP=\"${LOADER_INTERP}\"
CWARNFLAGS.main.c += -Wno-implicit-function-declaration
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_ZFS} != "no"
CFLAGS+= -DUSERBOOT_ZFS_SUPPORT
Index: stand/userboot/userboot/main.c
===================================================================
--- stand/userboot/userboot/main.c
+++ stand/userboot/userboot/main.c
@@ -47,6 +47,9 @@
/* 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 @@
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 @@
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)
{
@@ -138,6 +198,14 @@
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;
Index: stand/userboot/userboot/version
===================================================================
--- stand/userboot/userboot/version
+++ stand/userboot/userboot/version
@@ -1,4 +1,5 @@
$FreeBSD$
+1.2: Userboot with lua or forth
1.1: Initial userland boot
Index: stand/userboot/userboot_4th/Makefile
===================================================================
--- /dev/null
+++ stand/userboot/userboot_4th/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+LOADER_INTERP=4th
+
+.include "../userboot/Makefile"
+
Index: stand/userboot/userboot_lua/Makefile
===================================================================
--- /dev/null
+++ stand/userboot/userboot_lua/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+LOADER_INTERP=lua
+
+.include "../userboot/Makefile"
+
Index: usr.sbin/bhyveload/bhyveload.c
===================================================================
--- usr.sbin/bhyveload/bhyveload.c
+++ usr.sbin/bhyveload/bhyveload.c
@@ -75,6 +75,7 @@
#include <getopt.h>
#include <libgen.h>
#include <limits.h>
+#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -98,6 +99,13 @@
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 @@
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 @@
/* 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 @@
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 @@
loader = strdup(optarg);
if (loader == NULL)
err(EX_OSERR, "malloc");
+ explicit_loader = 1;
break;
case 'm':
@@ -747,6 +779,13 @@
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 @@
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 @@
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);

File Metadata

Mime Type
text/plain
Expires
Sun, Oct 19, 3:21 AM (9 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23907888
Default Alt Text
D16945.id47533.diff (9 KB)

Event Timeline