summaryrefslogtreecommitdiff
path: root/usr.sbin/vmd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2016-11-26 20:03:43 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2016-11-26 20:03:43 +0000
commitad7fd0a6998e319d102963734595c29a6515c62a (patch)
tree248eb0804fb2c2652d1c50a9dcc958ca0773c35c /usr.sbin/vmd
parent61ff2306bc056ac447e38f4ab358282107d9a4a5 (diff)
Implement basic support for boot.conf(8) on the disk image.
Like the real boot loader, load and parse hd0a:/etc/boot.conf from the first disk and fall back to /bsd. Not all boot loader options are supported, but it at least does set device, set image, and boot -acds (eg. for booting single-user). For example, it can now boot install60.fs that includes a boot.conf with "set image /6.0/amd64/bsd.rd": vmctl start install -c -d install60.fs -d OpenBSD.img This pseudo-bootloader is only needed without BIOS and could potentially be replaced in the future. OK mlarkin@
Diffstat (limited to 'usr.sbin/vmd')
-rw-r--r--usr.sbin/vmd/Makefile4
-rw-r--r--usr.sbin/vmd/disklabel.c78
-rw-r--r--usr.sbin/vmd/loadfile.h4
-rw-r--r--usr.sbin/vmd/loadfile_elf.c22
-rw-r--r--usr.sbin/vmd/vmboot.c316
-rw-r--r--usr.sbin/vmd/vmboot.h7
-rw-r--r--usr.sbin/vmd/vmd.c9
-rw-r--r--usr.sbin/vmd/vmd.h18
-rw-r--r--usr.sbin/vmd/vmm.c11
9 files changed, 400 insertions, 69 deletions
diff --git a/usr.sbin/vmd/Makefile b/usr.sbin/vmd/Makefile
index a4666ba3a07..39fd337c581 100644
--- a/usr.sbin/vmd/Makefile
+++ b/usr.sbin/vmd/Makefile
@@ -1,11 +1,11 @@
-# $OpenBSD: Makefile,v 1.11 2016/11/24 07:58:55 reyk Exp $
+# $OpenBSD: Makefile,v 1.12 2016/11/26 20:03:42 reyk Exp $
.if ${MACHINE} == "amd64" || ${MACHINE} == "i386"
PROG= vmd
SRCS= vmm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
SRCS+= vmd.c control.c log.c priv.c proc.c config.c ns8250.c i8253.c
-SRCS+= vmboot.c ufs.c
+SRCS+= vmboot.c ufs.c disklabel.c
SRCS+= parse.y
CFLAGS+= -Wall -I${.CURDIR}
diff --git a/usr.sbin/vmd/disklabel.c b/usr.sbin/vmd/disklabel.c
new file mode 100644
index 00000000000..125f701a08a
--- /dev/null
+++ b/usr.sbin/vmd/disklabel.c
@@ -0,0 +1,78 @@
+/* $OpenBSD: disklabel.c,v 1.1 2016/11/26 20:03:42 reyk Exp $ */
+/* $NetBSD: disklabel.c,v 1.3 1994/10/26 05:44:42 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)disklabel.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include "vmboot.h"
+
+/*
+ * Compute checksum for disk label.
+ */
+u_int
+dkcksum(struct disklabel *lp)
+{
+ const u_short *start, *end;
+ u_short sum = 0;
+
+ start = (u_short *)lp;
+ end = (u_short *)&lp->d_partitions[lp->d_npartitions];
+ while (start < end)
+ sum ^= *start++;
+ return (sum);
+}
+
+char *
+getdisklabel(char *buf, struct disklabel *lp)
+{
+ struct disklabel *dlp, *elp;
+ char *msg = NULL;
+
+ elp = (struct disklabel *)(buf + DEV_BSIZE - sizeof(*dlp));
+ for (dlp = (struct disklabel *)buf; dlp <= elp;
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
+ if (msg == NULL)
+ msg = "no disk label";
+ } else if (dlp->d_npartitions > MAXPARTITIONS ||
+ dkcksum(dlp) != 0)
+ msg = "disk label corrupted";
+ else {
+ *lp = *dlp;
+ msg = NULL;
+ break;
+ }
+ }
+ return (msg);
+}
+
diff --git a/usr.sbin/vmd/loadfile.h b/usr.sbin/vmd/loadfile.h
index aff1a9fd052..7bd1e97c8b3 100644
--- a/usr.sbin/vmd/loadfile.h
+++ b/usr.sbin/vmd/loadfile.h
@@ -1,5 +1,5 @@
/* $NetBSD: loadfile.h,v 1.1 1999/04/28 09:08:50 christos Exp $ */
-/* $OpenBSD: loadfile.h,v 1.6 2016/11/24 07:58:55 reyk Exp $ */
+/* $OpenBSD: loadfile.h,v 1.7 2016/11/26 20:03:42 reyk Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -74,6 +74,6 @@
#define NPTE_PG (PAGE_SIZE / sizeof(pt_entry_t))
int loadelf_main(FILE *, struct vm_create_params *,
- struct vcpu_reg_state *);
+ struct vcpu_reg_state *, uint32_t, uint32_t);
#include <machine/loadfile_machdep.h>
diff --git a/usr.sbin/vmd/loadfile_elf.c b/usr.sbin/vmd/loadfile_elf.c
index 7ec9b2ae063..645bfc3ec00 100644
--- a/usr.sbin/vmd/loadfile_elf.c
+++ b/usr.sbin/vmd/loadfile_elf.c
@@ -1,5 +1,5 @@
/* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
-/* $OpenBSD: loadfile_elf.c,v 1.21 2016/11/24 07:58:55 reyk Exp $ */
+/* $OpenBSD: loadfile_elf.c,v 1.22 2016/11/26 20:03:42 reyk Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -122,7 +122,7 @@ static int elf32_exec(FILE *, Elf32_Ehdr *, u_long *, int);
static int elf64_exec(FILE *, Elf64_Ehdr *, u_long *, int);
static size_t create_bios_memmap(struct vm_create_params *, bios_memmap_t *);
static uint32_t push_bootargs(bios_memmap_t *, size_t);
-static size_t push_stack(uint32_t, uint32_t);
+static size_t push_stack(uint32_t, uint32_t, uint32_t, uint32_t);
static void push_gdt(void);
static size_t mread(FILE *, paddr_t, size_t);
static void marc4random_buf(paddr_t, int);
@@ -265,13 +265,16 @@ push_pt(void)
* fd: file descriptor of a kernel file to load
* vcp: the VM create parameters, holding the exact memory map
* (out) vrs: register state to set on init for this kernel
+ * bootdev: the optional non-default boot device
+ * howto: optionel boot flags for the kernel
*
* Return values:
* 0 if successful
* various error codes returned from read(2) or loadelf functions
*/
int
-loadelf_main(FILE *fp, struct vm_create_params *vcp, struct vcpu_reg_state *vrs)
+loadelf_main(FILE *fp, struct vm_create_params *vcp,
+ struct vcpu_reg_state *vrs, uint32_t bootdev, uint32_t howto)
{
int r;
uint32_t bootargsz;
@@ -298,7 +301,7 @@ loadelf_main(FILE *fp, struct vm_create_params *vcp, struct vcpu_reg_state *vrs)
push_pt();
n = create_bios_memmap(vcp, memmap);
bootargsz = push_bootargs(memmap, n);
- stacksize = push_stack(bootargsz, marks[MARK_END]);
+ stacksize = push_stack(bootargsz, marks[MARK_END], bootdev, howto);
#ifdef __i386__
vrs->vrs_gprs[VCPU_REGS_EIP] = (uint32_t)marks[MARK_ENTRY];
@@ -434,12 +437,14 @@ push_bootargs(bios_memmap_t *memmap, size_t n)
* Parameters:
* bootargsz: size of boot arguments
* end: kernel 'end' symbol value
+ * bootdev: the optional non-default boot device
+ * howto: optionel boot flags for the kernel
*
* Return values:
* size of the stack
*/
static size_t
-push_stack(uint32_t bootargsz, uint32_t end)
+push_stack(uint32_t bootargsz, uint32_t end, uint32_t bootdev, uint32_t howto)
{
uint32_t stack[1024];
uint16_t loc;
@@ -447,14 +452,17 @@ push_stack(uint32_t bootargsz, uint32_t end)
memset(&stack, 0, sizeof(stack));
loc = 1024;
+ if (bootdev == 0)
+ bootdev = MAKEBOOTDEV(0x4, 0, 0, 0, 0); /* bootdev: sd0a */
+
stack[--loc] = BOOTARGS_PAGE;
stack[--loc] = bootargsz;
stack[--loc] = 0; /* biosbasemem */
stack[--loc] = 0; /* biosextmem */
stack[--loc] = end;
stack[--loc] = 0x0e;
- stack[--loc] = MAKEBOOTDEV(0x4, 0, 0, 0, 0); /* bootdev: sd0a */
- stack[--loc] = 0x0;
+ stack[--loc] = bootdev;
+ stack[--loc] = howto;
write_mem(STACK_PAGE, &stack, PAGE_SIZE);
diff --git a/usr.sbin/vmd/vmboot.c b/usr.sbin/vmd/vmboot.c
index b11e3b9e721..b7275a9a6b8 100644
--- a/usr.sbin/vmd/vmboot.c
+++ b/usr.sbin/vmd/vmboot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmboot.c,v 1.2 2016/11/25 22:28:58 reyk Exp $ */
+/* $OpenBSD: vmboot.c,v 1.3 2016/11/26 20:03:42 reyk Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -17,6 +17,7 @@
*/
#include <sys/param.h>
+#include <sys/reboot.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/disklabel.h>
@@ -27,16 +28,201 @@
#include <stdio.h>
#include <unistd.h>
+#include <ctype.h>
#include <fcntl.h>
#include <err.h>
+#include <vis.h>
#include "vmd.h"
#include "vmboot.h"
+int vmboot_bootconf(char *, size_t, struct vmboot_params *);
+int vmboot_bootcmd(char *, struct vmboot_params *);
+int vmboot_bootargs(int argc, char **argv, struct vmboot_params *);
+uint32_t vmboot_bootdevice(const char *);
+
int vmboot_strategy(void *, int, daddr32_t, size_t, void *, size_t *);
-off_t vmboot_findopenbsd(struct open_file *, off_t);
+off_t vmboot_findopenbsd(struct open_file *, off_t, struct disklabel *);
void *vmboot_loadfile(struct open_file *, char *, size_t *);
+int
+vmboot_bootcmd(char *line, struct vmboot_params *bp)
+{
+ char *p, *args[16];
+ int ac = 0;
+ char *last;
+
+ for (args[0] = NULL, (p = strtok_r(line, " ", &last)); p;
+ (p = strtok_r(NULL, " ", &last))) {
+ if (ac < (int)(sizeof(args) / sizeof(args[0])) - 1)
+ args[ac++] = p;
+ }
+ if (ac == 0)
+ return (0);
+ args[ac] = NULL;
+
+ /*
+ * Subset of boot.conf(8) options
+ */
+ if (strcmp("boot", args[0]) == 0)
+ return (vmboot_bootargs(ac, args, bp));
+ else if (strcmp("set", args[0]) == 0) {
+ if (ac < 3)
+ return (-1);
+ if (strcmp("device", args[1]) == 0) {
+ if ((size_t)strnvis(bp->vbp_device, args[2],
+ sizeof(bp->vbp_device), VIS_SAFE) >=
+ sizeof(bp->vbp_device)) {
+ log_warnx("invalid device name");
+ return (-1);
+ }
+ } else if (strcmp("image", args[1]) == 0) {
+ if ((size_t)strnvis(bp->vbp_image, args[2],
+ sizeof(bp->vbp_image), VIS_SAFE) >=
+ sizeof(bp->vbp_image)) {
+ log_warnx("invalid image name");
+ return (-1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+int
+vmboot_bootargs(int ac, char **av, struct vmboot_params *bp)
+{
+ char *p;
+ int ch;
+
+ if (ac < 2)
+ return (0);
+
+ /*
+ * Syntax is based on boot(8): boot "[hd0a[:/file]] [-asdc]"
+ */
+ if (*av[1] != '-') {
+ if ((p = strchr(av[1], ':')) != NULL) {
+ *p++ = '\0';
+ if (!strlen(p)) {
+ log_warnx("invalid file syntax");
+ return (-1);
+ }
+ if ((size_t)strnvis(bp->vbp_device, av[1],
+ sizeof(bp->vbp_device), VIS_SAFE) >=
+ sizeof(bp->vbp_device)) {
+ log_warnx("invalid device name");
+ return (-1);
+ }
+ } else {
+ p = av[1];
+ }
+ if ((size_t)strnvis(bp->vbp_image, p,
+ sizeof(bp->vbp_image), VIS_SAFE) >= sizeof(bp->vbp_image)) {
+ log_warnx("invalid image name");
+ return (-1);
+ }
+ ac--;
+ av++;
+ }
+
+ optreset = optind = opterr = 1;
+ while ((ch = getopt(ac, av, "acds")) != -1) {
+ switch (ch) {
+ case 'a':
+ bp->vbp_howto |= RB_ASKNAME;
+ break;
+ case 'c':
+ bp->vbp_howto |= RB_CONFIG;
+ break;
+ case 'd':
+ bp->vbp_howto |= RB_KDB;
+ break;
+ case 's':
+ bp->vbp_howto |= RB_SINGLE;
+ break;
+ default:
+ log_warnx("invalid boot option: %c", ch);
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+uint32_t
+vmboot_bootdevice(const char *word)
+{
+ uint32_t bootdev = 0;
+ int disk, part;
+
+ if (strlen(word) != strlen("hd0a")) {
+ log_warnx("invalid boot device: %s", word);
+ goto done;
+ }
+
+ if (strncmp("hd", word, 2) != 0) {
+ log_warnx("unsupported boot device type: %s", word);
+ goto done;
+ }
+
+ disk = (int)word[2];
+ part = (int)word[3];
+
+ if (!(isdigit(disk) && isalpha(part) && islower(part))) {
+ log_warnx("invalid boot partition: %s", word);
+ goto done;
+ }
+
+ disk -= '0';
+ part -= 'a';
+
+ if (disk != 0 || part > MAXPARTITIONS) {
+ log_warnx("cannot boot from device: %s", word);
+ goto done;
+ }
+
+ bootdev = MAKEBOOTDEV(0x4, 0, 0, disk, part);
+
+ done:
+ /* returns 0 on error */
+ return (bootdev);
+}
+
+int
+vmboot_bootconf(char *conf, size_t size, struct vmboot_params *bp)
+{
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ if ((fp = fmemopen(conf, size, "r")) == NULL) {
+ log_debug("%s: failed to boot.conf memory stream", __func__);
+ return (-1);
+ }
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ buf[strcspn(buf, "\n")] = '\0';
+ vmboot_bootcmd(buf, bp);
+ }
+ fclose(fp);
+
+ if (strlen(bp->vbp_device))
+ log_debug("%s: set device %s", __func__, bp->vbp_device);
+ if (strlen(bp->vbp_image))
+ log_debug("%s: set image %s", __func__, bp->vbp_image);
+ if (bp->vbp_howto) {
+ snprintf(buf, sizeof(buf), "boot -%s%s%s%s",
+ (bp->vbp_howto & RB_ASKNAME) ? "a" : "",
+ (bp->vbp_howto & RB_CONFIG) ? "c" : "",
+ (bp->vbp_howto & RB_KDB) ? "d" : "",
+ (bp->vbp_howto & RB_SINGLE) ? "s" : "");
+ log_debug("%s: %s", __func__, buf);
+ }
+
+ return (0);
+}
+
+
/*
* For ufs.c
*/
@@ -52,32 +238,27 @@ struct open_file vmboot_file = {
.f_devdata = NULL
};
-struct vmboot {
- int fd;
- off_t partoff;
-};
-
int
vmboot_strategy(void *devdata, int rw,
daddr32_t blk, size_t size, void *buf, size_t *rsize)
{
- struct vmboot *vmboot = devdata;
- ssize_t rlen;
+ struct vmboot_params *vmboot = devdata;
+ ssize_t rlen;
- if (vmboot->fd == -1)
+ if (vmboot->vbp_fd == -1)
return (EIO);
switch (rw) {
case F_READ:
- rlen = pread(vmboot->fd, buf, size,
- (blk + vmboot->partoff) * DEV_BSIZE);
+ rlen = pread(vmboot->vbp_fd, buf, size,
+ (blk + vmboot->vbp_partoff) * DEV_BSIZE);
if (rlen == -1)
return (errno);
*rsize = (size_t)rlen;
break;
case F_WRITE:
- rlen = pwrite(vmboot->fd, buf, size,
- (blk + vmboot->partoff) * DEV_BSIZE);
+ rlen = pwrite(vmboot->vbp_fd, buf, size,
+ (blk + vmboot->vbp_partoff) * DEV_BSIZE);
if (rlen == -1)
return (errno);
*rsize = (size_t)rlen;
@@ -92,14 +273,15 @@ vmboot_strategy(void *devdata, int rw,
* Based on findopenbsd() from biosdev.c that was partially written by me.
*/
off_t
-vmboot_findopenbsd(struct open_file *f, off_t mbroff)
+vmboot_findopenbsd(struct open_file *f, off_t mbroff, struct disklabel *dl)
{
struct dos_mbr mbr;
struct dos_partition *dp;
off_t mbr_eoff = DOSBBSECTOR, nextebr;
int ret, i;
- static int maxebr = DOS_MAXEBR;
+ static int maxebr = DOS_MAXEBR;
size_t rsize;
+ char buf[DEV_BSIZE], *msg;
if (!maxebr--) {
log_debug("%s: too many extended partitions", __func__);
@@ -129,6 +311,20 @@ vmboot_findopenbsd(struct open_file *f, off_t mbroff)
if (dp->dp_typ == DOSPTYP_OPENBSD) {
if (dp->dp_start > (dp->dp_start + mbroff))
continue;
+
+ /* Load and parse the disk label */
+ ret = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ dp->dp_start + mbroff + DOS_LABELSECTOR,
+ sizeof(buf), buf, &rsize);
+ if (ret != 0 || rsize != sizeof(buf)) {
+ log_warn("could not load disk label");
+ return (-1);
+ }
+ if ((msg = getdisklabel(buf, dl)) != NULL) {
+ log_warnx("%s", msg);
+ return (-1);
+ }
+
return (dp->dp_start + mbroff);
}
@@ -144,7 +340,7 @@ vmboot_findopenbsd(struct open_file *f, off_t mbroff)
if (nextebr && nextebr != -1) {
mbroff = nextebr;
- return (vmboot_findopenbsd(f, mbroff));
+ return (vmboot_findopenbsd(f, mbroff, dl));
}
return (-1);
@@ -153,20 +349,18 @@ vmboot_findopenbsd(struct open_file *f, off_t mbroff)
void *
vmboot_loadfile(struct open_file *f, char *file, size_t *size)
{
- char *buf = NULL;
+ char *buf = NULL, *p = NULL;
struct stat st;
size_t rsize;
int ret;
*size = 0;
- if ((ret = ufs_open(file, f)) != 0) {
- log_debug("%s: failed to open hd0a:%s", __func__, file);
+ if ((ret = ufs_open(file, f)) != 0)
return (NULL);
- }
if ((ret = ufs_stat(f, &st)) != 0) {
- log_debug("%s: failed to stat hd0a:%s", __func__, file);
+ log_debug("%s: failed to stat %s", __func__, file);
goto done;
}
@@ -176,26 +370,29 @@ vmboot_loadfile(struct open_file *f, char *file, size_t *size)
}
if ((ret = ufs_read(f, buf, st.st_size, &rsize)) != 0) {
- log_debug("%s: failed to read hd0a:%s", __func__, file);
+ log_debug("%s: failed to read %s", __func__, file);
+ free(buf);
goto done;
}
*size = st.st_size;
+ p = buf;
done:
ufs_close(f);
- return (buf);
+ return (p);
}
FILE *
-vmboot_open(int kernel_fd, int disk_fd, void **boot)
+vmboot_open(int kernel_fd, int disk_fd, struct vmboot_params *vmboot)
{
- char file[PATH_MAX];
- char *buf = NULL;
- struct vmboot vmboot;
- size_t size;
- FILE *fp = NULL;
+ char file[PATH_MAX];
+ char *buf = NULL;
+ size_t size;
+ FILE *fp = NULL;
+ struct disklabel dl;
- *boot = NULL;
+ memset(vmboot, 0, sizeof(*vmboot));
+ memset(&dl, 0, sizeof(dl));
/* First open kernel directly if specified by fd */
if (kernel_fd != -1)
@@ -204,34 +401,67 @@ vmboot_open(int kernel_fd, int disk_fd, void **boot)
if (disk_fd == -1)
return (NULL);
- memset(&vmboot, 0, sizeof(vmboot));
- vmboot.fd = disk_fd;
- vmboot_file.f_devdata = &vmboot;
+ vmboot->vbp_fd = disk_fd;
+ vmboot_file.f_devdata = vmboot;
- /* XXX try and parse hd0a:/etc/boot.conf */
- strlcpy(file, VM_DEFAULT_KERNEL, sizeof(file));
-
- if ((vmboot.partoff = vmboot_findopenbsd(&vmboot_file, 0)) == -1) {
+ if ((vmboot->vbp_partoff =
+ vmboot_findopenbsd(&vmboot_file, 0, &dl)) == -1) {
log_debug("%s: could not find openbsd partition", __func__);
return (NULL);
}
- if ((buf = vmboot_loadfile(&vmboot_file, file, &size)) == NULL)
+ /* Set the default kernel boot device and image path */
+ strlcpy(vmboot->vbp_device, VM_DEFAULT_DEVICE,
+ sizeof(vmboot->vbp_device));
+ strlcpy(vmboot->vbp_image, VM_DEFAULT_KERNEL,
+ sizeof(vmboot->vbp_image));
+
+ /* Try to parse boot.conf to overwrite the default kernel path */
+ strlcpy(file, VM_BOOT_CONF, sizeof(file));
+ if ((buf = vmboot_loadfile(&vmboot_file, file, &size)) != NULL) {
+ if (vmboot_bootconf(buf, size, vmboot) == -1) {
+ free(buf);
+ return (NULL);
+ }
+ free(buf);
+ }
+
+ /* Parse boot device and find partition in disk label */
+ if ((vmboot->vbp_bootdev =
+ vmboot_bootdevice(vmboot->vbp_device)) == 0)
return (NULL);
- *boot = buf;
+ if (B_PARTITION(vmboot->vbp_bootdev) > dl.d_npartitions) {
+ log_debug("%s: invalid boot partition: %s",
+ __func__, vmboot->vbp_device);
+ return (NULL);
+ }
+ vmboot->vbp_partoff =
+ dl.d_partitions[B_PARTITION(vmboot->vbp_bootdev)].p_offset;
+
+ /* Load the kernel */
+ if ((buf = vmboot_loadfile(&vmboot_file,
+ vmboot->vbp_image, &size)) == NULL) {
+ log_debug("%s: failed to open kernel %s:%s", __func__,
+ vmboot->vbp_device, vmboot->vbp_image);
+ return (NULL);
+ }
+ vmboot->vbp_arg = buf;
if ((fp = fmemopen(buf, size, "r")) == NULL) {
log_debug("%s: failed to open memory stream", __func__);
free(buf);
- *boot = NULL;
+ vmboot->vbp_arg = NULL;
+ } else {
+ log_debug("%s: kernel %s:%s", __func__,
+ vmboot->vbp_device, vmboot->vbp_image);
}
return (fp);
}
void
-vmboot_close(FILE *fp, void *boot)
+vmboot_close(FILE *fp, struct vmboot_params *vmboot)
{
fclose(fp);
- free(boot);
+ free(vmboot->vbp_arg);
}
diff --git a/usr.sbin/vmd/vmboot.h b/usr.sbin/vmd/vmboot.h
index 1df187b28db..c81fa3cdc46 100644
--- a/usr.sbin/vmd/vmboot.h
+++ b/usr.sbin/vmd/vmboot.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmboot.h,v 1.1 2016/11/24 07:58:55 reyk Exp $ */
+/* $OpenBSD: vmboot.h,v 1.2 2016/11/26 20:03:42 reyk Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -59,6 +59,11 @@ struct open_file {
off_t f_offset;
};
+struct disklabel;
+
+u_int dkcksum(struct disklabel *);
+char *getdisklabel(char *, struct disklabel *);
+
int ufs_open(char *, struct open_file *);
int ufs_close(struct open_file *);
int ufs_read(struct open_file *, void *, size_t, size_t *);
diff --git a/usr.sbin/vmd/vmd.c b/usr.sbin/vmd/vmd.c
index a9693a64852..44fe0ddae37 100644
--- a/usr.sbin/vmd/vmd.c
+++ b/usr.sbin/vmd/vmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.c,v 1.44 2016/11/26 19:49:11 reyk Exp $ */
+/* $OpenBSD: vmd.c,v 1.45 2016/11/26 20:03:42 reyk Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
@@ -199,11 +199,8 @@ vmd_dispatch_vmm(int fd, struct privsep_proc *p, struct imsg *imsg)
break;
}
- log_info("%s: started vm %d successfully, "
- "kernel %s, tty %s", vcp->vcp_name, vcp->vcp_id,
- strlen(vcp->vcp_kernel) ?
- vcp->vcp_kernel : "hd0a:" VM_DEFAULT_KERNEL,
- vm->vm_ttyname);
+ log_info("%s: started vm %d successfully, tty %s",
+ vcp->vcp_name, vcp->vcp_id, vm->vm_ttyname);
break;
case IMSG_VMDOP_TERMINATE_VM_RESPONSE:
case IMSG_VMDOP_TERMINATE_VM_EVENT:
diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h
index 042cfa82b7f..f6993735d9e 100644
--- a/usr.sbin/vmd/vmd.h
+++ b/usr.sbin/vmd/vmd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmd.h,v 1.37 2016/11/26 19:49:11 reyk Exp $ */
+/* $OpenBSD: vmd.h,v 1.38 2016/11/26 20:03:42 reyk Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -38,6 +38,8 @@
#define SOCKET_NAME "/var/run/vmd.sock"
#define VMM_NODE "/dev/vmm"
#define VM_DEFAULT_KERNEL "/bsd"
+#define VM_DEFAULT_DEVICE "hd0a"
+#define VM_BOOT_CONF "/etc/boot.conf"
#define VM_NAME_MAX 64
#define VM_TTYNAME_MAX 16
#define MAX_TAP 256
@@ -106,6 +108,16 @@ struct vmop_create_params {
char vmc_ifgroup[VMM_MAX_NICS_PER_VM][IF_NAMESIZE];
};
+struct vmboot_params {
+ int vbp_fd;
+ off_t vbp_partoff;
+ char vbp_device[NAME_MAX];
+ char vbp_image[PATH_MAX];
+ uint32_t vbp_bootdev;
+ uint32_t vbp_howto;
+ char *vbp_arg;
+};
+
struct vmd_if {
char *vif_name;
char *vif_switch;
@@ -206,8 +218,8 @@ int config_getdisk(struct privsep *, struct imsg *);
int config_getif(struct privsep *, struct imsg *);
/* vmboot.c */
-FILE *vmboot_open(int, int, void **);
-void vmboot_close(FILE *, void *);
+FILE *vmboot_open(int, int, struct vmboot_params *);
+void vmboot_close(FILE *, struct vmboot_params *);
/* parse.y */
int parse_config(const char *);
diff --git a/usr.sbin/vmd/vmm.c b/usr.sbin/vmd/vmm.c
index f9d9a23d026..3168243ed87 100644
--- a/usr.sbin/vmd/vmm.c
+++ b/usr.sbin/vmd/vmm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vmm.c,v 1.57 2016/11/26 15:29:33 martijn Exp $ */
+/* $OpenBSD: vmm.c,v 1.58 2016/11/26 20:03:42 reyk Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -460,13 +460,13 @@ int
start_vm(struct imsg *imsg, uint32_t *id)
{
struct vm_create_params *vcp;
+ struct vmboot_params vmboot;
struct vmd_vm *vm;
size_t i;
int ret = EINVAL;
int fds[2], nicfds[VMM_MAX_NICS_PER_VM];
struct vcpu_reg_state vrs;
FILE *kernfp;
- void *boot;
if ((vm = vm_getbyvmid(imsg->hdr.peerid)) == NULL) {
log_warnx("%s: can't find vm", __func__);
@@ -569,17 +569,18 @@ start_vm(struct imsg *imsg, uint32_t *id)
/* Find and open kernel image */
if ((kernfp = vmboot_open(vm->vm_kernel,
- vm->vm_disks[0], &boot)) == NULL)
+ vm->vm_disks[0], &vmboot)) == NULL)
fatalx("failed to open kernel - exiting");
/* Load kernel image */
- ret = loadelf_main(kernfp, vcp, &vrs);
+ ret = loadelf_main(kernfp, vcp, &vrs,
+ vmboot.vbp_bootdev, vmboot.vbp_howto);
if (ret) {
errno = ret;
fatal("failed to load kernel - exiting");
}
- vmboot_close(kernfp, boot);
+ vmboot_close(kernfp, &vmboot);
if (vm->vm_kernel != -1)
close(vm->vm_kernel);