diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2016-11-26 20:03:43 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2016-11-26 20:03:43 +0000 |
commit | ad7fd0a6998e319d102963734595c29a6515c62a (patch) | |
tree | 248eb0804fb2c2652d1c50a9dcc958ca0773c35c /usr.sbin/vmd | |
parent | 61ff2306bc056ac447e38f4ab358282107d9a4a5 (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/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/vmd/disklabel.c | 78 | ||||
-rw-r--r-- | usr.sbin/vmd/loadfile.h | 4 | ||||
-rw-r--r-- | usr.sbin/vmd/loadfile_elf.c | 22 | ||||
-rw-r--r-- | usr.sbin/vmd/vmboot.c | 316 | ||||
-rw-r--r-- | usr.sbin/vmd/vmboot.h | 7 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.c | 9 | ||||
-rw-r--r-- | usr.sbin/vmd/vmd.h | 18 | ||||
-rw-r--r-- | usr.sbin/vmd/vmm.c | 11 |
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); |