diff options
Diffstat (limited to 'usr.sbin/vmd/vmboot.c')
-rw-r--r-- | usr.sbin/vmd/vmboot.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/usr.sbin/vmd/vmboot.c b/usr.sbin/vmd/vmboot.c index f17ae24ed34..44ceeb64a7e 100644 --- a/usr.sbin/vmd/vmboot.c +++ b/usr.sbin/vmd/vmboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmboot.c,v 1.4 2017/08/29 21:10:20 deraadt Exp $ */ +/* $OpenBSD: vmboot.c,v 1.5 2018/09/28 12:35:32 reyk Exp $ */ /* * Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org> @@ -35,6 +35,7 @@ #include "vmd.h" #include "vmboot.h" +#include "virtio.h" int vmboot_bootconf(char *, size_t, struct vmboot_params *); int vmboot_bootcmd(char *, struct vmboot_params *); @@ -243,21 +244,22 @@ vmboot_strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, size_t *rsize) { struct vmboot_params *vmboot = devdata; + struct virtio_backing *vfp = vmboot->vbp_arg; ssize_t rlen; - if (vmboot->vbp_fd == -1) + if (vfp == NULL) return (EIO); switch (rw) { case F_READ: - rlen = pread(vmboot->vbp_fd, buf, size, + rlen = vfp->pread(vfp->p, buf, size, (blk + vmboot->vbp_partoff) * DEV_BSIZE); if (rlen == -1) return (errno); *rsize = (size_t)rlen; break; case F_WRITE: - rlen = pwrite(vmboot->vbp_fd, buf, size, + rlen = vfp->pwrite(vfp->p, buf, size, (blk + vmboot->vbp_partoff) * DEV_BSIZE); if (rlen == -1) return (errno); @@ -383,15 +385,19 @@ vmboot_loadfile(struct open_file *f, char *file, size_t *size) } FILE * -vmboot_open(int kernel_fd, int disk_fd, struct vmboot_params *vmboot) +vmboot_open(int kernel_fd, int disk_fd, unsigned int disk_type, + struct vmboot_params *vmboot) { char file[PATH_MAX]; char *buf = NULL; size_t size; FILE *fp = NULL; struct disklabel dl; + struct virtio_backing *vfp; + off_t sz; memset(vmboot, 0, sizeof(*vmboot)); + memset(&vfp, 0, sizeof(vfp)); memset(&dl, 0, sizeof(dl)); /* First open kernel directly if specified by fd */ @@ -401,13 +407,33 @@ vmboot_open(int kernel_fd, int disk_fd, struct vmboot_params *vmboot) if (disk_fd == -1) return (NULL); + if ((vfp = calloc(1, sizeof(*vfp))) == NULL) + goto fail; + vmboot->vbp_type = disk_type; + vmboot->vbp_arg = vfp; + + switch (vmboot->vbp_type) { + case VMDF_RAW: + if (virtio_init_raw(vfp, &sz, disk_fd) == -1) { + log_debug("%s: could not open raw disk", __func__); + goto fail; + } + break; + case VMDF_QCOW2: + if (virtio_init_qcow2(vfp, &sz, disk_fd) == -1) { + log_debug("%s: could not open qcow2 disk", __func__); + goto fail; + } + break; + } + vmboot->vbp_fd = disk_fd; vmboot_file.f_devdata = vmboot; if ((vmboot->vbp_partoff = vmboot_findopenbsd(&vmboot_file, 0, &dl)) == -1) { log_debug("%s: could not find openbsd partition", __func__); - return (NULL); + goto fail; } /* Set the default kernel boot device and image path */ @@ -421,7 +447,7 @@ vmboot_open(int kernel_fd, int disk_fd, struct vmboot_params *vmboot) if ((buf = vmboot_loadfile(&vmboot_file, file, &size)) != NULL) { if (vmboot_bootconf(buf, size, vmboot) == -1) { free(buf); - return (NULL); + goto fail; } free(buf); } @@ -429,11 +455,11 @@ vmboot_open(int kernel_fd, int disk_fd, struct vmboot_params *vmboot) /* Parse boot device and find partition in disk label */ if ((vmboot->vbp_bootdev = vmboot_bootdevice(vmboot->vbp_device)) == 0) - return (NULL); + goto fail; if (B_PARTITION(vmboot->vbp_bootdev) > dl.d_npartitions) { log_debug("%s: invalid boot partition: %s", __func__, vmboot->vbp_device); - return (NULL); + goto fail; } vmboot->vbp_partoff = dl.d_partitions[B_PARTITION(vmboot->vbp_bootdev)].p_offset; @@ -443,25 +469,34 @@ vmboot_open(int kernel_fd, int disk_fd, struct vmboot_params *vmboot) vmboot->vbp_image, &size)) == NULL) { log_debug("%s: failed to open kernel %s:%s", __func__, vmboot->vbp_device, vmboot->vbp_image); - return (NULL); + goto fail; } - vmboot->vbp_arg = buf; + vmboot->vbp_buf = buf; if ((fp = fmemopen(buf, size, "r")) == NULL) { log_debug("%s: failed to open memory stream", __func__); free(buf); - vmboot->vbp_arg = NULL; + vmboot->vbp_buf = NULL; } else { log_debug("%s: kernel %s:%s", __func__, vmboot->vbp_device, vmboot->vbp_image); } return (fp); + fail: + vmboot_close(fp, vmboot); + return (NULL); } void vmboot_close(FILE *fp, struct vmboot_params *vmboot) { - fclose(fp); + struct virtio_backing *vfp = vmboot->vbp_arg; + + if (fp != NULL) + fclose(fp); + if (vfp != NULL) + vfp->close(vfp->p, 1); free(vmboot->vbp_arg); + free(vmboot->vbp_buf); } |