> On 12 Mar 2021, at 05:41, Mike Larkin <mlar...@nested.page> wrote:
> 
> On Thu, Mar 11, 2021 at 06:11:03PM -0500, Dave Voutila wrote:
>> tl;dr: tedu vmboot.{c,h}, ufs.c from vmd(8) to remove broken ability to
>> exract and boot a kernel image from a raw or qcow2 disk image
>> 
>> The following diff removes the ability to boot directly from a disk
>> image containing a FFS filesystem. No new functionality is added. It's
>> still possible to boot via a kernel image or with either disk or iso
>> images via seabios. (PXE booting should still work via a kernel image,
>> but I haven't tested it personally.)
>> 
>> Why remove this?
>> 
>> - since 6.7 switched to FFS2 as the default filesystem for new installs,
>>  the ability for vmd(8) to load a kernel and boot.conf from a disk
>>  image directly (without seabios) has been broken. tb@ apparently sent
>>  a diff to update support for FFS2 awhile back, but it never made it
>>  into the tree.
>> 
>> - on 5th Jan 2021, new ramdisks for amd64 have started shipping gzip'd,
>>  breaking the ability to load the bsd.rd directly as a kernel image for
>>  a vmd(8) guest without first uncompressing the image
>> 
>> Why not fix it?
>> 
>> - using bios (via seabios) works
>> 
>> - the FFS2 change happened ten months ago and afaict few if any have
>>  complained about the breakage, so I'm not sure the value in fixing
>>  it. vmctl(8) is still vague about supporting it per its man page and
>>  you still have to pass the disk image twice as a -b and -d arg if
>>  you're trying to avoid using seabios to boot an OpenBSD guest.
>> 
>> - Josh Rickmar reported the gzip issue on bugs@ and provided patches to
>>  add in support for compressed ramdisks and kernel images. In doing so,
>>  we found the easiest way to add gzip kernel image support was to drop
>>  support for FFS images since they require a call to fmemopen(3) while
>>  all the other logic uses fopen(3)/fdopen(3) calls and a file
>>  descriptor. I think it would be easier to get his patches into vmd(8)
>>  if they don't have to account for extracting kernels from disk
>>  images.
>> 
>> I can understand an argument to shy away from relying on seabios for
>> booting, but given it's readily available via fw_update(1) and is part
>> of the default behavior, I'd imagine most won't miss this feature.
>> 
>> If people ARE using direct booting of raw/qcow2 images (without using
>> seabios) please speak up and instead I can look into dusting off tb@'s
>> old diff.
>> 
> 
> reyk@ wrote that ffs module for vmd but since he has not stepped up to
> maintain it after the ffs2 switch, I vote to remove it. If someone wants
> to come back and fixup ffs2 support with the tb@ diff we can look at that
> when said person steps up.
> 
> ok mlarkin

I’m not using it anymore and I’m not interested in maintaining it. It was a 
nice feature for some tests and to boot small VMs in about a second but that’s 
about it.

Removing it makes sense.

Reyk

>> --
>> -Dave Voutila
>> 
>> 
>> Index: Makefile
>> ===================================================================
>> RCS file: /cvs/src/usr.sbin/vmd/Makefile,v
>> retrieving revision 1.24
>> diff -u -p -u -p -r1.24 Makefile
>> --- Makefile    23 Sep 2020 19:18:18 -0000    1.24
>> +++ Makefile    11 Mar 2021 22:10:08 -0000
>> @@ -5,7 +5,7 @@
>> PROG=        vmd
>> SRCS=        vmd.c control.c log.c priv.c proc.c config.c vmm.c
>> SRCS+=        vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
>> -SRCS+=        ns8250.c i8253.c vmboot.c ufs.c disklabel.c dhcp.c packet.c
>> +SRCS+=        ns8250.c i8253.c dhcp.c packet.c
>> SRCS+=        parse.y atomicio.c vioscsi.c vioraw.c vioqcow2.c fw_cfg.c
>> 
>> CFLAGS+=    -Wall -I${.CURDIR}
>> Index: loadfile.h
>> ===================================================================
>> RCS file: /cvs/src/usr.sbin/vmd/loadfile.h,v
>> retrieving revision 1.12
>> diff -u -p -u -p -r1.12 loadfile.h
>> --- loadfile.h    16 May 2019 21:16:04 -0000    1.12
>> +++ loadfile.h    11 Mar 2021 22:10:08 -0000
>> @@ -73,8 +73,6 @@
>> #define PML2_PAGE 0x13000
>> #define NPTE_PG (PAGE_SIZE / sizeof(uint64_t))
>> 
>> -int loadfile_elf(FILE *, struct vm_create_params *,
>> -    struct vcpu_reg_state *, uint32_t, uint32_t, unsigned int);
>> +int loadfile_elf(FILE *, struct vm_create_params *, struct vcpu_reg_state 
>> *);
>> 
>> size_t mread(FILE *, paddr_t, size_t);
>> -
>> Index: loadfile_elf.c
>> ===================================================================
>> RCS file: /cvs/src/usr.sbin/vmd/loadfile_elf.c,v
>> retrieving revision 1.36
>> diff -u -p -u -p -r1.36 loadfile_elf.c
>> --- loadfile_elf.c    26 Oct 2020 04:04:31 -0000    1.36
>> +++ loadfile_elf.c    11 Mar 2021 22:10:10 -0000
>> @@ -118,8 +118,8 @@ static void setsegment(struct mem_segmen
>> 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, bios_bootmac_t *);
>> -static size_t push_stack(uint32_t, uint32_t, uint32_t, uint32_t);
>> +static uint32_t push_bootargs(bios_memmap_t *, size_t);
>> +static size_t push_stack(uint32_t, uint32_t);
>> static void push_gdt(void);
>> static void push_pt_32(void);
>> static void push_pt_64(void);
>> @@ -263,16 +263,13 @@ push_pt_64(void)
>>  *  various error codes returned from read(2) or loadelf functions
>>  */
>> int
>> -loadfile_elf(FILE *fp, struct vm_create_params *vcp,
>> -    struct vcpu_reg_state *vrs, uint32_t bootdev, uint32_t howto,
>> -    unsigned int bootdevice)
>> +loadfile_elf(FILE *fp, struct vm_create_params *vcp, struct vcpu_reg_state 
>> *vrs)
>> {
>>    int r, is_i386 = 0;
>>    uint32_t bootargsz;
>>    size_t n, stacksize;
>>    u_long marks[MARK_MAX];
>>    bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1];
>> -    bios_bootmac_t bm, *bootmac = NULL;
>> 
>>    if ((r = fread(&hdr, 1, sizeof(hdr), fp)) != sizeof(hdr))
>>        return 1;
>> @@ -303,13 +300,9 @@ loadfile_elf(FILE *fp, struct vm_create_
>>    else
>>        push_pt_64();
>> 
>> -    if (bootdevice & VMBOOTDEV_NET) {
>> -        bootmac = &bm;
>> -        memcpy(bootmac, vcp->vcp_macs[0], ETHER_ADDR_LEN);
>> -    }
>>    n = create_bios_memmap(vcp, memmap);
>> -    bootargsz = push_bootargs(memmap, n, bootmac);
>> -    stacksize = push_stack(bootargsz, marks[MARK_END], bootdev, howto);
>> +    bootargsz = push_bootargs(memmap, n);
>> +    stacksize = push_stack(bootargsz, marks[MARK_END]);
>> 
>>    vrs->vrs_gprs[VCPU_REGS_RIP] = (uint64_t)marks[MARK_ENTRY];
>>    vrs->vrs_gprs[VCPU_REGS_RSP] = (uint64_t)(STACK_PAGE + PAGE_SIZE) - 
>> stacksize;
>> @@ -388,9 +381,9 @@ create_bios_memmap(struct vm_create_para
>>  *  The size of the bootargs
>>  */
>> static uint32_t
>> -push_bootargs(bios_memmap_t *memmap, size_t n, bios_bootmac_t *bootmac)
>> +push_bootargs(bios_memmap_t *memmap, size_t n)
>> {
>> -    uint32_t memmap_sz, consdev_sz, bootmac_sz, i;
>> +    uint32_t memmap_sz, consdev_sz, i;
>>    bios_consdev_t consdev;
>>    uint32_t ba[1024];
>> 
>> @@ -414,15 +407,6 @@ push_bootargs(bios_memmap_t *memmap, siz
>>    memcpy(&ba[i + 3], &consdev, sizeof(bios_consdev_t));
>>    i += consdev_sz / sizeof(int);
>> 
>> -    if (bootmac) {
>> -        bootmac_sz = 3 * sizeof(int) + (sizeof(bios_bootmac_t) + 3) & ~3;
>> -        ba[i] = 0x7;   /* bootmac */
>> -        ba[i + 1] = bootmac_sz;
>> -        ba[i + 2] = bootmac_sz;
>> -        memcpy(&ba[i + 3], bootmac, sizeof(bios_bootmac_t));
>> -        i += bootmac_sz / sizeof(int);
>> -    }
>> -
>>    ba[i++] = 0xFFFFFFFF; /* BOOTARG_END */
>> 
>>    write_mem(BOOTARGS_PAGE, ba, PAGE_SIZE);
>> @@ -458,7 +442,7 @@ push_bootargs(bios_memmap_t *memmap, siz
>>  *  size of the stack
>>  */
>> static size_t
>> -push_stack(uint32_t bootargsz, uint32_t end, uint32_t bootdev, uint32_t 
>> howto)
>> +push_stack(uint32_t bootargsz, uint32_t end)
>> {
>>    uint32_t stack[1024];
>>    uint16_t loc;
>> @@ -466,17 +450,14 @@ push_stack(uint32_t bootargsz, uint32_t
>>    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] = bootdev;
>> -    stack[--loc] = howto;
>> +    stack[--loc] = MAKEBOOTDEV(0x4, 0, 0, 0, 0); /* bootdev: sd0a */
>> +    stack[--loc] = 0;
>> 
>>    write_mem(STACK_PAGE, &stack, PAGE_SIZE);
>> 
>> Index: ufs.c
>> ===================================================================
>> RCS file: ufs.c
>> diff -N ufs.c
>> --- ufs.c    7 Oct 2017 19:48:30 -0000    1.6
>> +++ /dev/null    1 Jan 1970 00:00:00 -0000
>> @@ -1,721 +0,0 @@
>> -/*    $OpenBSD: ufs.c,v 1.6 2017/10/07 19:48:30 guenther Exp $    */
>> -/*    $NetBSD: ufs.c,v 1.16 1996/09/30 16:01:22 ws Exp $    */
>> -
>> -/*-
>> - * Copyright (c) 1993
>> - *    The Regents of the University of California.  All rights reserved.
>> - *
>> - * This code is derived from software contributed to Berkeley by
>> - * The Mach Operating System project at Carnegie-Mellon University.
>> - *
>> - * 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.
>> - *
>> - *
>> - * Copyright (c) 1990, 1991 Carnegie Mellon University
>> - * All Rights Reserved.
>> - *
>> - * Author: David Golub
>> - *
>> - * Permission to use, copy, modify and distribute this software and its
>> - * documentation is hereby granted, provided that both the copyright
>> - * notice and this permission notice appear in all copies of the
>> - * software, derivative works or modified versions, and any portions
>> - * thereof, and that both notices appear in supporting documentation.
>> - *
>> - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
>> - * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
>> - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
>> - *
>> - * Carnegie Mellon requests users of this software to return to
>> - *
>> - *  Software Distribution Coordinator  or  software.distribut...@cs.cmu.edu
>> - *  School of Computer Science
>> - *  Carnegie Mellon University
>> - *  Pittsburgh PA 15213-3890
>> - *
>> - * any improvements or extensions that they make and grant Carnegie the
>> - * rights to redistribute these changes.
>> - */
>> -
>> -/*
>> - *    Stand-alone file reading package.
>> - */
>> -
>> -#include <sys/param.h>    /* DEV_BSIZE MAXBSIZE */
>> -#include <sys/time.h>
>> -#include <sys/stat.h>
>> -#include <ufs/ffs/fs.h>
>> -#include <ufs/ufs/dinode.h>
>> -#include <ufs/ufs/dir.h>
>> -
>> -#include <limits.h>
>> -
>> -#include "vmboot.h"
>> -
>> -/* Used in the kernel by libsa */
>> -#define alloc        malloc
>> -#define free(_p, _n)    free(_p)
>> -#define twiddle()    do { } while(0)
>> -#define NO_READDIR    1
>> -
>> -/*
>> - * In-core open file.
>> - */
>> -struct file {
>> -    off_t        f_seekp;    /* seek pointer */
>> -    struct fs    *f_fs;        /* pointer to super-block */
>> -    struct ufs1_dinode    f_di;        /* copy of on-disk inode */
>> -    int        f_nindir[NIADDR];
>> -                    /* number of blocks mapped by
>> -                       indirect block at level i */
>> -    char        *f_blk[NIADDR];    /* buffer for indirect block at
>> -                       level i */
>> -    size_t        f_blksize[NIADDR];
>> -                    /* size of buffer */
>> -    daddr32_t    f_blkno[NIADDR];/* disk address of block in buffer */
>> -    char        *f_buf;        /* buffer for data block */
>> -    size_t        f_buf_size;    /* size of data block */
>> -    daddr32_t    f_buf_blkno;    /* block number of data block */
>> -};
>> -
>> -static int    read_inode(ufsino_t, struct open_file *);
>> -static int    block_map(struct open_file *, daddr32_t, daddr32_t *);
>> -static int    buf_read_file(struct open_file *, char **, size_t *);
>> -static int    search_directory(char *, struct open_file *, ufsino_t *);
>> -static int    ufs_close_internal(struct file *);
>> -#ifdef COMPAT_UFS
>> -static void    ffs_oldfscompat(struct fs *);
>> -#endif
>> -
>> -/*
>> - * Read a new inode into a file structure.
>> - */
>> -static int
>> -read_inode(ufsino_t inumber, struct open_file *f)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -    struct fs *fs = fp->f_fs;
>> -    char *buf;
>> -    size_t rsize;
>> -    int rc;
>> -
>> -    /*
>> -     * Read inode and save it.
>> -     */
>> -    buf = alloc(fs->fs_bsize);
>> -    twiddle();
>> -    rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
>> -        fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
>> -        buf, &rsize);
>> -    if (rc)
>> -        goto out;
>> -    if (rsize != (size_t)fs->fs_bsize) {
>> -        rc = EIO;
>> -        goto out;
>> -    }
>> -
>> -    {
>> -        struct ufs1_dinode *dp;
>> -
>> -        dp = (struct ufs1_dinode *)buf;
>> -        fp->f_di = dp[ino_to_fsbo(fs, inumber)];
>> -    }
>> -
>> -    /*
>> -     * Clear out the old buffers
>> -     */
>> -    {
>> -        int level;
>> -
>> -        for (level = 0; level < NIADDR; level++)
>> -            fp->f_blkno[level] = -1;
>> -        fp->f_buf_blkno = -1;
>> -        fp->f_seekp = 0;
>> -    }
>> -out:
>> -    free(buf, fs->fs_bsize);
>> -    return (rc);
>> -}
>> -
>> -/*
>> - * Given an offset in a file, find the disk block number that
>> - * contains that block.
>> - */
>> -static int
>> -block_map(struct open_file *f, daddr32_t file_block, daddr32_t 
>> *disk_block_p)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -    daddr32_t ind_block_num, *ind_p;
>> -    struct fs *fs = fp->f_fs;
>> -    int level, idx, rc;
>> -
>> -    /*
>> -     * Index structure of an inode:
>> -     *
>> -     * di_db[0..NDADDR-1]    hold block numbers for blocks
>> -     *            0..NDADDR-1
>> -     *
>> -     * di_ib[0]        index block 0 is the single indirect block
>> -     *            holds block numbers for blocks
>> -     *            NDADDR .. NDADDR + NINDIR(fs)-1
>> -     *
>> -     * di_ib[1]        index block 1 is the double indirect block
>> -     *            holds block numbers for INDEX blocks for blocks
>> -     *            NDADDR + NINDIR(fs) ..
>> -     *            NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
>> -     *
>> -     * di_ib[2]        index block 2 is the triple indirect block
>> -     *            holds block numbers for double-indirect
>> -     *            blocks for blocks
>> -     *            NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
>> -     *            NDADDR + NINDIR(fs) + NINDIR(fs)**2
>> -     *                + NINDIR(fs)**3 - 1
>> -     */
>> -
>> -    if (file_block < NDADDR) {
>> -        /* Direct block. */
>> -        *disk_block_p = fp->f_di.di_db[file_block];
>> -        return (0);
>> -    }
>> -
>> -    file_block -= NDADDR;
>> -
>> -    /*
>> -     * nindir[0] = NINDIR
>> -     * nindir[1] = NINDIR**2
>> -     * nindir[2] = NINDIR**3
>> -     *    etc
>> -     */
>> -    for (level = 0; level < NIADDR; level++) {
>> -        if (file_block < fp->f_nindir[level])
>> -            break;
>> -        file_block -= fp->f_nindir[level];
>> -    }
>> -    if (level == NIADDR) {
>> -        /* Block number too high */
>> -        return (EFBIG);
>> -    }
>> -
>> -    ind_block_num = fp->f_di.di_ib[level];
>> -
>> -    for (; level >= 0; level--) {
>> -        if (ind_block_num == 0) {
>> -            *disk_block_p = 0;    /* missing */
>> -            return (0);
>> -        }
>> -
>> -        if (fp->f_blkno[level] != ind_block_num) {
>> -            if (fp->f_blk[level] == NULL)
>> -                fp->f_blk[level] =
>> -                    alloc(fs->fs_bsize);
>> -            twiddle();
>> -            rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
>> -                fsbtodb(fp->f_fs, ind_block_num), fs->fs_bsize,
>> -                fp->f_blk[level], &fp->f_blksize[level]);
>> -            if (rc)
>> -                return (rc);
>> -            if (fp->f_blksize[level] != (size_t)fs->fs_bsize)
>> -                return (EIO);
>> -            fp->f_blkno[level] = ind_block_num;
>> -        }
>> -
>> -        ind_p = (daddr32_t *)fp->f_blk[level];
>> -
>> -        if (level > 0) {
>> -            idx = file_block / fp->f_nindir[level - 1];
>> -            file_block %= fp->f_nindir[level - 1];
>> -        } else
>> -            idx = file_block;
>> -
>> -        ind_block_num = ind_p[idx];
>> -    }
>> -
>> -    *disk_block_p = ind_block_num;
>> -    return (0);
>> -}
>> -
>> -/*
>> - * Read a portion of a file into an internal buffer.  Return
>> - * the location in the buffer and the amount in the buffer.
>> - */
>> -static int
>> -buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -    struct fs *fs = fp->f_fs;
>> -    daddr32_t file_block, disk_block;
>> -    size_t block_size;
>> -    long off;
>> -    int rc;
>> -
>> -    off = blkoff(fs, fp->f_seekp);
>> -    file_block = lblkno(fs, fp->f_seekp);
>> -    block_size = dblksize(fs, &fp->f_di, (u_int64_t)file_block);
>> -
>> -    if (file_block != fp->f_buf_blkno) {
>> -        rc = block_map(f, file_block, &disk_block);
>> -        if (rc)
>> -            return (rc);
>> -
>> -        if (fp->f_buf == NULL)
>> -            fp->f_buf = alloc(fs->fs_bsize);
>> -
>> -        if (disk_block == 0) {
>> -            memset(fp->f_buf, 0, block_size);
>> -            fp->f_buf_size = block_size;
>> -        } else {
>> -            twiddle();
>> -            rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
>> -                fsbtodb(fs, disk_block),
>> -                block_size, fp->f_buf, &fp->f_buf_size);
>> -            if (rc)
>> -                return (rc);
>> -        }
>> -
>> -        fp->f_buf_blkno = file_block;
>> -    }
>> -
>> -    /*
>> -     * Return address of byte in buffer corresponding to
>> -     * offset, and size of remainder of buffer after that
>> -     * byte.
>> -     */
>> -    *buf_p = fp->f_buf + off;
>> -    *size_p = block_size - off;
>> -
>> -    /*
>> -     * But truncate buffer at end of file.
>> -     */
>> -    if (*size_p > fp->f_di.di_size - fp->f_seekp)
>> -        *size_p = fp->f_di.di_size - fp->f_seekp;
>> -
>> -    return (0);
>> -}
>> -
>> -/*
>> - * Search a directory for a name and return its
>> - * i_number.
>> - */
>> -static int
>> -search_directory(char *name, struct open_file *f, ufsino_t *inumber_p)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -    int namlen, length, rc;
>> -    struct direct *dp, *edp;
>> -    size_t buf_size;
>> -    char *buf;
>> -
>> -    length = strlen(name);
>> -
>> -    fp->f_seekp = 0;
>> -    while ((u_int64_t)fp->f_seekp < fp->f_di.di_size) {
>> -        rc = buf_read_file(f, &buf, &buf_size);
>> -        if (rc)
>> -            return (rc);
>> -
>> -        dp = (struct direct *)buf;
>> -        edp = (struct direct *)(buf + buf_size);
>> -        while (dp < edp) {
>> -            if (dp->d_ino == 0)
>> -                goto next;
>> -#if BYTE_ORDER == LITTLE_ENDIAN
>> -            if (fp->f_fs->fs_maxsymlinklen <= 0)
>> -                namlen = dp->d_type;
>> -            else
>> -#endif
>> -                namlen = dp->d_namlen;
>> -            if (namlen == length &&
>> -                !strcmp(name, dp->d_name)) {
>> -                /* found entry */
>> -                *inumber_p = dp->d_ino;
>> -                return (0);
>> -            }
>> -        next:
>> -            dp = (struct direct *)((char *)dp + dp->d_reclen);
>> -        }
>> -        fp->f_seekp += buf_size;
>> -    }
>> -    return (ENOENT);
>> -}
>> -
>> -/*
>> - * Open a file.
>> - */
>> -int
>> -ufs_open(char *path, struct open_file *f)
>> -{
>> -    char namebuf[PATH_MAX+1], *cp, *ncp, *buf = NULL;
>> -    ufsino_t inumber, parent_inumber;
>> -    int rc, c, nlinks = 0;
>> -    struct file *fp;
>> -    size_t buf_size;
>> -    struct fs *fs;
>> -
>> -    /* allocate file system specific data structure */
>> -    fp = alloc(sizeof(struct file));
>> -    memset(fp, 0, sizeof(struct file));
>> -    f->f_fsdata = (void *)fp;
>> -
>> -    /* allocate space and read super block */
>> -    fs = alloc(SBSIZE);
>> -    fp->f_fs = fs;
>> -    twiddle();
>> -    rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
>> -        SBLOCK, SBSIZE, (char *)fs, &buf_size);
>> -    if (rc)
>> -        goto out;
>> -
>> -    if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
>> -        (size_t)fs->fs_bsize > MAXBSIZE ||
>> -        (size_t)fs->fs_bsize < sizeof(struct fs)) {
>> -        rc = EINVAL;
>> -        goto out;
>> -    }
>> -#ifdef COMPAT_UFS
>> -    ffs_oldfscompat(fs);
>> -#endif
>> -
>> -    /*
>> -     * Calculate indirect block levels.
>> -     */
>> -    {
>> -        int mult;
>> -        int level;
>> -
>> -        mult = 1;
>> -        for (level = 0; level < NIADDR; level++) {
>> -            mult *= NINDIR(fs);
>> -            fp->f_nindir[level] = mult;
>> -        }
>> -    }
>> -
>> -    inumber = ROOTINO;
>> -    if ((rc = read_inode(inumber, f)) != 0)
>> -        goto out;
>> -
>> -    cp = path;
>> -    while (*cp) {
>> -
>> -        /*
>> -         * Remove extra separators
>> -         */
>> -        while (*cp == '/')
>> -            cp++;
>> -        if (*cp == '\0')
>> -            break;
>> -
>> -        /*
>> -         * Check that current node is a directory.
>> -         */
>> -        if ((fp->f_di.di_mode & IFMT) != IFDIR) {
>> -            rc = ENOTDIR;
>> -            goto out;
>> -        }
>> -
>> -        /*
>> -         * Get next component of path name.
>> -         */
>> -        {
>> -            int len = 0;
>> -
>> -            ncp = cp;
>> -            while ((c = *cp) != '\0' && c != '/') {
>> -                if (++len > MAXNAMLEN) {
>> -                    rc = ENOENT;
>> -                    goto out;
>> -                }
>> -                cp++;
>> -            }
>> -            *cp = '\0';
>> -        }
>> -
>> -        /*
>> -         * Look up component in current directory.
>> -         * Save directory inumber in case we find a
>> -         * symbolic link.
>> -         */
>> -        parent_inumber = inumber;
>> -        rc = search_directory(ncp, f, &inumber);
>> -        *cp = c;
>> -        if (rc)
>> -            goto out;
>> -
>> -        /*
>> -         * Open next component.
>> -         */
>> -        if ((rc = read_inode(inumber, f)) != 0)
>> -            goto out;
>> -
>> -        /*
>> -         * Check for symbolic link.
>> -         */
>> -        if ((fp->f_di.di_mode & IFMT) == IFLNK) {
>> -            u_int64_t link_len = fp->f_di.di_size;
>> -            size_t len;
>> -
>> -            len = strlen(cp);
>> -
>> -            if (link_len + len > PATH_MAX ||
>> -                ++nlinks > SYMLOOP_MAX) {
>> -                rc = ENOENT;
>> -                goto out;
>> -            }
>> -
>> -            bcopy(cp, &namebuf[link_len], len + 1);
>> -
>> -            if (link_len < (u_int64_t)fs->fs_maxsymlinklen) {
>> -                bcopy(fp->f_di.di_shortlink, namebuf, link_len);
>> -            } else {
>> -                /*
>> -                 * Read file for symbolic link
>> -                 */
>> -                daddr32_t disk_block;
>> -                fs = fp->f_fs;
>> -
>> -                if (!buf)
>> -                    buf = alloc(fs->fs_bsize);
>> -                rc = block_map(f, (daddr32_t)0, &disk_block);
>> -                if (rc)
>> -                    goto out;
>> -
>> -                twiddle();
>> -                rc = (f->f_dev->dv_strategy)(f->f_devdata,
>> -                    F_READ, fsbtodb(fs, disk_block),
>> -                    fs->fs_bsize, buf, &buf_size);
>> -                if (rc)
>> -                    goto out;
>> -
>> -                bcopy(buf, namebuf, link_len);
>> -            }
>> -
>> -            /*
>> -             * If relative pathname, restart at parent directory.
>> -             * If absolute pathname, restart at root.
>> -             */
>> -            cp = namebuf;
>> -            if (*cp != '/')
>> -                inumber = parent_inumber;
>> -            else
>> -                inumber = ROOTINO;
>> -
>> -            if ((rc = read_inode(inumber, f)) != 0)
>> -                goto out;
>> -        }
>> -    }
>> -
>> -    /*
>> -     * Found terminal component.
>> -     */
>> -    rc = 0;
>> -out:
>> -    if (buf)
>> -        free(buf, fs->fs_bsize);
>> -    if (rc)
>> -        (void)ufs_close_internal(fp);
>> -
>> -    return (rc);
>> -}
>> -
>> -int
>> -ufs_close(struct open_file *f)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -
>> -    f->f_fsdata = NULL;
>> -    if (fp == NULL)
>> -        return (0);
>> -
>> -    return (ufs_close_internal(fp));
>> -}
>> -
>> -static int
>> -ufs_close_internal(struct file *fp)
>> -{
>> -    int level;
>> -
>> -    for (level = 0; level < NIADDR; level++) {
>> -        if (fp->f_blk[level])
>> -            free(fp->f_blk[level], fp->f_fs->fs_bsize);
>> -    }
>> -    if (fp->f_buf)
>> -        free(fp->f_buf, fp->f_fs->fs_bsize);
>> -    free(fp->f_fs, SBSIZE);
>> -    free(fp, sizeof(struct file));
>> -    return (0);
>> -}
>> -
>> -/*
>> - * Copy a portion of a file into kernel memory.
>> - * Cross block boundaries when necessary.
>> - */
>> -int
>> -ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -    char *buf, *addr = start;
>> -    size_t csize, buf_size;
>> -    int rc = 0;
>> -
>> -    while (size != 0) {
>> -        if ((u_int64_t)fp->f_seekp >= fp->f_di.di_size)
>> -            break;
>> -
>> -        rc = buf_read_file(f, &buf, &buf_size);
>> -        if (rc)
>> -            break;
>> -
>> -        csize = size;
>> -        if (csize > buf_size)
>> -            csize = buf_size;
>> -
>> -        bcopy(buf, addr, csize);
>> -
>> -        fp->f_seekp += csize;
>> -        addr += csize;
>> -        size -= csize;
>> -    }
>> -    if (resid)
>> -        *resid = size;
>> -    return (rc);
>> -}
>> -
>> -/*
>> - * Not implemented.
>> - */
>> -int
>> -ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
>> -{
>> -
>> -    return (EROFS);
>> -}
>> -
>> -off_t
>> -ufs_seek(struct open_file *f, off_t offset, int where)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -
>> -    switch (where) {
>> -    case SEEK_SET:
>> -        fp->f_seekp = offset;
>> -        break;
>> -    case SEEK_CUR:
>> -        fp->f_seekp += offset;
>> -        break;
>> -    case SEEK_END:
>> -        fp->f_seekp = fp->f_di.di_size - offset;
>> -        break;
>> -    default:
>> -        return (-1);
>> -    }
>> -    return (fp->f_seekp);
>> -}
>> -
>> -int
>> -ufs_stat(struct open_file *f, struct stat *sb)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -
>> -    /* only important stuff */
>> -    sb->st_mode = fp->f_di.di_mode;
>> -    sb->st_uid = fp->f_di.di_uid;
>> -    sb->st_gid = fp->f_di.di_gid;
>> -    sb->st_size = fp->f_di.di_size;
>> -    return (0);
>> -}
>> -
>> -#ifndef    NO_READDIR
>> -int
>> -ufs_readdir(struct open_file *f, char *name)
>> -{
>> -    struct file *fp = (struct file *)f->f_fsdata;
>> -    struct direct *dp, *edp;
>> -    size_t buf_size;
>> -    int rc, namlen;
>> -    char *buf;
>> -
>> -    if (name == NULL)
>> -        fp->f_seekp = 0;
>> -    else {
>> -            /* end of dir */
>> -        if ((u_int64_t)fp->f_seekp >= fp->f_di.di_size) {
>> -            *name = '\0';
>> -            return -1;
>> -        }
>> -
>> -        do {
>> -            if ((rc = buf_read_file(f, &buf, &buf_size)) != 0)
>> -                return rc;
>> -
>> -            dp = (struct direct *)buf;
>> -            edp = (struct direct *)(buf + buf_size);
>> -            while (dp < edp && dp->d_ino == 0)
>> -                dp = (struct direct *)((char *)dp + dp->d_reclen);
>> -            fp->f_seekp += buf_size -
>> -                ((u_int8_t *)edp - (u_int8_t *)dp);
>> -        } while (dp >= edp);
>> -
>> -#if BYTE_ORDER == LITTLE_ENDIAN
>> -        if (fp->f_fs->fs_maxsymlinklen <= 0)
>> -            namlen = dp->d_type;
>> -        else
>> -#endif
>> -            namlen = dp->d_namlen;
>> -        strncpy(name, dp->d_name, namlen + 1);
>> -
>> -        fp->f_seekp += dp->d_reclen;
>> -    }
>> -
>> -    return 0;
>> -}
>> -#endif
>> -
>> -#ifdef COMPAT_UFS
>> -/*
>> - * Sanity checks for old file systems.
>> - *
>> - * XXX - goes away some day.
>> - */
>> -static void
>> -ffs_oldfscompat(struct fs *fs)
>> -{
>> -    int i;
>> -
>> -    fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);    /* XXX */
>> -    fs->fs_interleave = max(fs->fs_interleave, 1);        /* XXX */
>> -    if (fs->fs_postblformat == FS_42POSTBLFMT)        /* XXX */
>> -        fs->fs_nrpos = 8;                /* XXX */
>> -    if (fs->fs_inodefmt < FS_44INODEFMT) {            /* XXX */
>> -        quad_t sizepb = fs->fs_bsize;            /* XXX */
>> -                                /* XXX */
>> -        fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;    /* XXX */
>> -        for (i = 0; i < NIADDR; i++) {            /* XXX */
>> -            sizepb *= NINDIR(fs);            /* XXX */
>> -            fs->fs_maxfilesize += sizepb;        /* XXX */
>> -        }                        /* XXX */
>> -        fs->fs_qbmask = ~fs->fs_bmask;            /* XXX */
>> -        fs->fs_qfmask = ~fs->fs_fmask;            /* XXX */
>> -    }                            /* XXX */
>> -}
>> -#endif
>> Index: vm.c
>> ===================================================================
>> RCS file: /cvs/src/usr.sbin/vmd/vm.c,v
>> retrieving revision 1.59
>> diff -u -p -u -p -r1.59 vm.c
>> --- vm.c    13 Feb 2021 07:56:26 -0000    1.59
>> +++ vm.c    11 Mar 2021 22:10:22 -0000
>> @@ -278,7 +278,6 @@ start_vm(struct vmd_vm *vm, int fd)
>>    int             nicfds[VMM_MAX_NICS_PER_VM];
>>    int             ret;
>>    FILE            *fp;
>> -    struct vmboot_params     vmboot;
>>    size_t             i;
>>    struct vm_rwregs_params  vrp;
>> 
>> @@ -332,14 +331,11 @@ start_vm(struct vmd_vm *vm, int fd)
>>        memcpy(&vrs, &vcpu_init_flat64, sizeof(vrs));
>> 
>>        /* Find and open kernel image */
>> -        if ((fp = vmboot_open(vm->vm_kernel,
>> -            vm->vm_disks[0], vmc->vmc_diskbases[0],
>> -            vmc->vmc_disktypes[0], &vmboot)) == NULL)
>> +        if ((fp = fdopen(vm->vm_kernel, "r")) == NULL)
>>            fatalx("failed to open kernel - exiting");
>> 
>>        /* Load kernel image */
>> -        ret = loadfile_elf(fp, vcp, &vrs,
>> -            vmboot.vbp_bootdev, vmboot.vbp_howto, vmc->vmc_bootdevice);
>> +        ret = loadfile_elf(fp, vcp, &vrs);
>> 
>>        /*
>>         * Try BIOS as a fallback (only if it was provided as an image
>> @@ -351,7 +347,8 @@ start_vm(struct vmd_vm *vm, int fd)
>>        if (ret)
>>            fatal("failed to load kernel or BIOS - exiting");
>> 
>> -        vmboot_close(fp, &vmboot);
>> +        if (fp)
>> +            fclose(fp);
>>    }
>> 
>>    if (vm->vm_kernel != -1)
>> Index: vmboot.c
>> ===================================================================
>> RCS file: vmboot.c
>> diff -N vmboot.c
>> --- vmboot.c    10 Dec 2020 16:58:03 -0000    1.8
>> +++ /dev/null    1 Jan 1970 00:00:00 -0000
>> @@ -1,501 +0,0 @@
>> -/*    $OpenBSD: vmboot.c,v 1.8 2020/12/10 16:58:03 krw Exp $    */
>> -
>> -/*
>> - * Copyright (c) 2016 Reyk Floeter <r...@openbsd.org>
>> - *
>> - * Permission to use, copy, modify, and distribute this software for any
>> - * purpose with or without fee is hereby granted, provided that the above
>> - * copyright notice and this permission notice appear in all copies.
>> - *
>> - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
>> - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
>> - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>> - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
>> - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
>> - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> - */
>> -
>> -#include <sys/param.h>    /* DEV_BSIZE roundup */
>> -#include <sys/reboot.h>
>> -#include <sys/time.h>
>> -#include <sys/stat.h>
>> -#include <sys/disklabel.h>
>> -
>> -#include <ufs/ffs/fs.h>
>> -#include <ufs/ufs/dinode.h>
>> -#include <ufs/ufs/dir.h>
>> -
>> -#include <stdio.h>
>> -#include <unistd.h>
>> -#include <ctype.h>
>> -#include <fcntl.h>
>> -#include <err.h>
>> -#include <vis.h>
>> -
>> -#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 *);
>> -int     vmboot_bootargs(int argc, char **argv, struct vmboot_params *);
>> -uint32_t vmboot_bootdevice(const char *);
>> -
>> -int     vmboot_strategy(void *, int, daddr_t, size_t, void *, size_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
>> - */
>> -
>> -struct devsw vmboot_devsw = {
>> -    .dv_name =    "vmboot",
>> -    .dv_strategy =    vmboot_strategy,
>> -    /* other fields are not needed */
>> -};
>> -
>> -struct open_file vmboot_file = {
>> -    .f_dev =    &vmboot_devsw,
>> -    .f_devdata =     NULL
>> -};
>> -
>> -int
>> -vmboot_strategy(void *devdata, int rw,
>> -    daddr_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;
>> -    off_t             off;
>> -
>> -    if (vfp == NULL)
>> -        return (EIO);
>> -
>> -    off = (blk + vmboot->vbp_partoff) * DEV_BSIZE;
>> -    switch (rw) {
>> -    case F_READ:
>> -        rlen = vfp->pread(vfp->p, buf, size, off);
>> -        if (rlen == -1)
>> -            return (errno);
>> -        *rsize = (size_t)rlen;
>> -        break;
>> -    case F_WRITE:
>> -        rlen = vfp->pwrite(vfp->p, buf, size, off);
>> -        if (rlen == -1)
>> -            return (errno);
>> -        *rsize = (size_t)rlen;
>> -        break;
>> -    default:
>> -        return (EINVAL);
>> -    }
>> -    return (0);
>> -}
>> -
>> -/*
>> - * Based on findopenbsd() from biosdev.c that was partially written by me.
>> - */
>> -off_t
>> -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;
>> -    size_t             rsize;
>> -    char             buf[DEV_BSIZE], *msg;
>> -
>> -    if (!maxebr--) {
>> -        log_debug("%s: too many extended partitions", __func__);
>> -        return (-1);
>> -    }
>> -
>> -    memset(&mbr, 0, sizeof(mbr));
>> -    ret = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
>> -        mbroff, sizeof(mbr), &mbr, &rsize);
>> -    if (ret != 0 || rsize != sizeof(mbr)) {
>> -        log_debug("%s: failed to read MBR", __func__);
>> -        return (-1);
>> -    }
>> -
>> -    if (mbr.dmbr_sign != DOSMBR_SIGNATURE) {
>> -        log_debug("%s: bad MBR signature", __func__);
>> -        return (-1);
>> -    }
>> -
>> -    /* Search for the first OpenBSD partition */
>> -    nextebr = 0;
>> -    for (i = 0; i < NDOSPART; i++) {
>> -        dp = &mbr.dmbr_parts[i];
>> -        if (!dp->dp_size)
>> -            continue;
>> -
>> -        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);
>> -        }
>> -
>> -        if (!nextebr && (dp->dp_typ == DOSPTYP_EXTEND ||
>> -            dp->dp_typ == DOSPTYP_EXTENDL)) {
>> -            nextebr = dp->dp_start + mbr_eoff;
>> -            if (nextebr < dp->dp_start)
>> -                nextebr = -1;
>> -            if (mbr_eoff == DOSBBSECTOR)
>> -                mbr_eoff = dp->dp_start;
>> -        }
>> -    }
>> -
>> -    if (nextebr && nextebr != -1) {
>> -        mbroff = nextebr;
>> -        return (vmboot_findopenbsd(f, mbroff, dl));
>> -    }
>> -
>> -    return (-1);
>> -}
>> -
>> -void *
>> -vmboot_loadfile(struct open_file *f, char *file, size_t *size)
>> -{
>> -    char        *buf = NULL, *p = NULL;
>> -    struct stat     st;
>> -    size_t         rsize;
>> -    int         ret;
>> -
>> -    *size = 0;
>> -
>> -    if ((ret = ufs_open(file, f)) != 0)
>> -        return (NULL);
>> -
>> -    if ((ret = ufs_stat(f, &st)) != 0) {
>> -        log_debug("%s: failed to stat %s", __func__, file);
>> -        goto done;
>> -    }
>> -
>> -    if ((buf = calloc(1, roundup(st.st_size, DEV_BSIZE))) == NULL) {
>> -        log_debug("%s: failed to allocate buffer", __func__);
>> -        goto done;
>> -    }
>> -
>> -    if ((ret = ufs_read(f, buf, st.st_size, &rsize)) != 0) {
>> -        log_debug("%s: failed to read %s", __func__, file);
>> -        free(buf);
>> -        goto done;
>> -    }
>> -
>> -    *size = st.st_size;
>> -    p = buf;
>> - done:
>> -    ufs_close(f);
>> -    return (p);
>> -}
>> -
>> -FILE *
>> -vmboot_open(int kernel_fd, int *disk_fd, int nfd, 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 */
>> -    if (kernel_fd != -1)
>> -        return (fdopen(kernel_fd, "r"));
>> -
>> -    if (disk_fd == NULL || nfd < 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_raw_init(vfp, &sz, disk_fd, nfd) == -1) {
>> -            log_debug("%s: could not open raw disk", __func__);
>> -            goto fail;
>> -        }
>> -        break;
>> -    case VMDF_QCOW2:
>> -        if (virtio_qcow2_init(vfp, &sz, disk_fd, nfd) == -1) {
>> -            log_debug("%s: could not open qcow2 disk", __func__);
>> -            goto fail;
>> -        }
>> -        break;
>> -    }
>> -
>> -    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__);
>> -        goto fail;
>> -    }
>> -
>> -    /* 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);
>> -            goto fail;
>> -        }
>> -        free(buf);
>> -    }
>> -
>> -    /* Parse boot device and find partition in disk label */
>> -    if ((vmboot->vbp_bootdev =
>> -        vmboot_bootdevice(vmboot->vbp_device)) == 0)
>> -        goto fail;
>> -    if (B_PARTITION(vmboot->vbp_bootdev) > dl.d_npartitions) {
>> -        log_debug("%s: invalid boot partition: %s",
>> -            __func__, vmboot->vbp_device);
>> -        goto fail;
>> -    }
>> -    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);
>> -        goto fail;
>> -    }
>> -    vmboot->vbp_buf = buf;
>> -
>> -    if ((fp = fmemopen(buf, size, "r")) == NULL) {
>> -        log_debug("%s: failed to open memory stream", __func__);
>> -        free(buf);
>> -        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)
>> -{
>> -    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);
>> -}
>> Index: vmboot.h
>> ===================================================================
>> RCS file: vmboot.h
>> diff -N vmboot.h
>> --- vmboot.h    10 Dec 2020 16:58:03 -0000    1.3
>> +++ /dev/null    1 Jan 1970 00:00:00 -0000
>> @@ -1,75 +0,0 @@
>> -/*    $OpenBSD: vmboot.h,v 1.3 2020/12/10 16:58:03 krw Exp $    */
>> -
>> -/*
>> - * Copyright (c) 2016 Reyk Floeter <r...@openbsd.org>
>> - *
>> - * Permission to use, copy, modify, and distribute this software for any
>> - * purpose with or without fee is hereby granted, provided that the above
>> - * copyright notice and this permission notice appear in all copies.
>> - *
>> - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
>> - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
>> - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>> - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
>> - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
>> - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> - */
>> -
>> -#include <sys/types.h>
>> -#include <sys/stat.h>
>> -#include <sys/stdarg.h>
>> -#include <sys/stdint.h>
>> -
>> -#include <errno.h>
>> -#include <string.h>
>> -#include <stdlib.h>
>> -#include <stdio.h>
>> -
>> -#ifndef VMBOOT_H
>> -#define VMBOOT_H
>> -
>> -#define    F_READ        1
>> -#define    F_WRITE        2
>> -
>> -struct open_file;
>> -
>> -struct fs_ops {
>> -    int    (*open)(char *, struct open_file *);
>> -    int    (*close)(struct open_file *);
>> -    int    (*read)(struct open_file *, void *, size_t, size_t *);
>> -    int    (*write)(struct open_file *, void *, size_t, size_t *);
>> -    off_t    (*seek)(struct open_file *, off_t, int);
>> -    int    (*stat)(struct open_file *, struct stat *);
>> -    int    (*readdir)(struct open_file *, char *);
>> -};
>> -
>> -struct devsw {
>> -    char    *dv_name;
>> -    int    (*dv_strategy)(void *, int, daddr_t, size_t,
>> -        void *, size_t *);
>> -};
>> -
>> -struct open_file {
>> -    int        f_flags;
>> -    struct devsw    *f_dev;
>> -    void        *f_devdata;
>> -    struct fs_ops    *f_ops;
>> -    void        *f_fsdata;
>> -    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 *);
>> -int    ufs_write(struct open_file *, void *, size_t, size_t *);
>> -off_t    ufs_seek(struct open_file *, off_t offset, int);
>> -int    ufs_stat(struct open_file *, struct stat *);
>> -int    ufs_readdir(struct open_file *, char *);
>> -
>> -#endif /* VMBOOT_H */
>> Index: vmd.h
>> ===================================================================
>> RCS file: /cvs/src/usr.sbin/vmd/vmd.h,v
>> retrieving revision 1.101
>> diff -u -p -u -p -r1.101 vmd.h
>> --- vmd.h    23 Sep 2020 19:18:18 -0000    1.101
>> +++ vmd.h    11 Mar 2021 22:10:23 -0000
>> @@ -228,8 +228,6 @@ struct vmboot_params {
>>    off_t             vbp_partoff;
>>    char             vbp_device[PATH_MAX];
>>    char             vbp_image[PATH_MAX];
>> -    uint32_t         vbp_bootdev;
>> -    uint32_t         vbp_howto;
>>    unsigned int         vbp_type;
>>    void            *vbp_arg;
>>    char            *vbp_buf;
>> 
> 

Reply via email to