On Thu, Mar 11, 2021 at 10:32:08AM -0500, Dave Voutila wrote:
> 
> Josh Rickmar writes:
> 
> > On Wed, Mar 10, 2021 at 04:56:03PM -0500, Dave Voutila wrote:
> >>
> >> Josh Rickmar writes:
> >>
> >> > On Wed, Mar 10, 2021 at 01:11:30PM -0500, Josh Rickmar wrote:
> >> >> On Tue, Mar 09, 2021 at 09:36:49PM -0800, Mike Larkin wrote:
> >> >> > On Mon, Mar 08, 2021 at 05:10:27PM -0500, Josh Rickmar wrote:
> >> >> > > On Mon, Mar 08, 2021 at 11:03:10PM +0100, Klemens Nanni wrote:
> >> >> > > > On Mon, Mar 08, 2021 at 04:50:53PM -0500, Josh Rickmar wrote:
> >> >> > > > > >Synopsis:      vmm/vmd fails to boot bsd.rd
> >> >> > > > > >Category:      vmm
> >> >> > > > > >Environment:
> >> >> > > > >         System      : OpenBSD 6.9
> >> >> > > > >         Details     : OpenBSD 6.9-beta (GENERIC.MP) #385: Mon 
> >> >> > > > > Mar  8 12:57:12 MST 2021
> >> >> > > > >                          
> >> >> > > > > [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> >> >> > > > >
> >> >> > > > >         Architecture: OpenBSD.amd64
> >> >> > > > >         Machine     : amd64
> >> >> > > > > >Description:
> >> >> > > > >
> >> >> > > > > vmm/vmd fails to boot /bsd.rd from a recent snapshot, however, 
> >> >> > > > > bsd.sp
> >> >> > > > > is able to be booted in this manner.
> >> >> > > > This is most likely due to the recent switch to compressed bsd.rd;
> >> >> > > > dry a gzcat(1)ed copy of bsd.rd instead.
> >> >> > >
> >> >> > > Ah, yes this works.
> >> >> > >
> >> >> > > Is this expected behavior or should vmd be taught how to read the
> >> >> > > compressed kernel?
> >> >> > >
> >> >> >
> >> >> > Sure. A diff would be welcome (libz is already in the tree and ready 
> >> >> > to use for
> >> >> > this).
> >> >>
> >> >> I expect this may need some cleanup, but with this patch I am able to
> >> >> boot the compressed bsd.rd.
> >> >>
> >> >> It replaces passing the kernel image around as a FILE* to a wrapper
> >> >> struct that may represent either a FILE* or gzFile.  The struct points
> >> >> to a function pointer to dispatch to the correct read or seek
> >> >> functions.
> >> >>
> >> >> This isn't wrapping gztell, which is used to discover the size of the
> >> >> bios firmware image, and so that will continue to error if you try to
> >> >> load a compressed bios.  I don't think we would want to wrap that,
> >> >> since seeking to the end to discover the size would result in
> >> >> decompressing everything twice.
> >> >
> >> > Hmm, let's rename "stdio" to "stream" for the regular uncompressed
> >> > files.  Otherwise this diff is the same as before.
> >>
> >> I believe you can simplify this and assume the file is gzip compressed
> >> and wrap the file descriptor with a call to gzdopen(3) to create a
> >> gzFile. The gz{read,write,tell,etc.}(3) calls should operate on both
> >> gzip compressed and non-compressed files (in "transparent mode").
> >>
> >> That's at least my experience using gzdopen(3) and gzread(3).
> >
> > Thanks for the tip, I missed that transparent mode existed. Here's an
> > updated diff.  I've tested this booting OpenBSD/amd64 both from
> > compressed and uncompressed kernels, and booting OpenBSD and Linux
> > from a disk installation and BIOS, but there are some problems
> > introduced by this approach.
> >
> > I am sure that the codepath in vmboot_open where an OpenBSD kernel is
> > found in a disk image is not correct anymore.  fmemopen creates a
> > FILE* with no file descriptor for fileno to return for gzdopen, but we
> > want to return a gzFile.  I wasn't able to hit this codepath while
> > testing though; kernel_fd was never -1 even with vmctl start -B disk.
> 
> mlarkin: Is the ability to extract a boot.conf and kernel image from a
> UFS disk image needed anymore? I dug up the commit from 4 years ago (26
> Nov 2016) and I believe it predates booting with seabios being the
> default.
> 
> The commit message from reyk@:
> 
> ---
> 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@
> ---
> 
> What reyk@ was doing isn't possible anymore as vmd(8) by default will
> try to load the bios from /etc/firmware/vmm-bios before trying to boot
> from the provided disk image. If that's the case, Josh can simplify his
> diff and we can potentially remove the ufs handling logic and file(s)
> from vmd(8).

It is still possible to bypass seabios using -b disk -d disk. This would
need updating to ufs2 however. I sent out a diff doing that, but got no
feedback, so I suspect I'm the only one who has been using this. FWIW I
have no objection to removing that code.

My understanding is that the only motivation for not using seabios is
the licensing.

> 
> Happy to take this off bugs@ in a side discussion via email.
> 
> >
> > This also still does not support compressed BIOS images (if we care),
> > since gzseek does not work with SEEK_END.  So instead, the image size
> > is being discovered using fstat(2) and only when the file was opened
> > in transparent mode.
> >
> 
> AFAIK, seabios is not built compressed so this shouldn't be a problem.
> 
> > diff refs/heads/master refs/heads/vmd-gzip
> > blob - 1770ac337a9996c76fb09de6f04909b3bb890658
> > blob + 49e2771d7e1a27a44d9deccbb7cc8830b0ed4544
> > --- usr.sbin/vmd/Makefile
> > +++ usr.sbin/vmd/Makefile
> > @@ -14,7 +14,7 @@ CFLAGS+=  -Wmissing-declarations
> >  CFLAGS+=   -Wshadow -Wpointer-arith -Wcast-qual
> >  CFLAGS+=   -Wsign-compare
> >
> > -LDADD+=            -lutil -lpthread -levent
> > +LDADD+=            -lutil -lpthread -levent -lz
> >  DPADD+=            ${LIBUTIL} ${LIBPTHREAD} ${LIBEVENT}
> >
> >  YFLAGS=
> > blob - de7fd5f270dc1b900c11ed082fb0b4f94acc01b0
> > blob + 578d046d5e1bcd176cb59d7fddd72ba967928691
> > --- usr.sbin/vmd/loadfile.h
> > +++ usr.sbin/vmd/loadfile.h
> > @@ -30,6 +30,8 @@
> >   * POSSIBILITY OF SUCH DAMAGE.
> >   */
> >
> > +#include <zlib.h>
> > +
> >  /*
> >   * Array indices in the u_long position array
> >   */
> > @@ -73,8 +75,8 @@
> >  #define PML2_PAGE 0x13000
> >  #define NPTE_PG (PAGE_SIZE / sizeof(uint64_t))
> >
> > -int loadfile_elf(FILE *, struct vm_create_params *,
> > +int loadfile_elf(gzFile, struct vm_create_params *,
> >      struct vcpu_reg_state *, uint32_t, uint32_t, unsigned int);
> >
> > -size_t mread(FILE *, paddr_t, size_t);
> > +size_t mread(gzFile, paddr_t, size_t);
> >
> > blob - 116094260948b50b9f1eda63d3241b77bfddb39d
> > blob + 1fddcfe38bedea79933febe581b7c0e3cc053327
> > --- usr.sbin/vmd/loadfile_elf.c
> > +++ usr.sbin/vmd/loadfile_elf.c
> > @@ -115,8 +115,8 @@ union {
> >
> >  static void setsegment(struct mem_segment_descriptor *, uint32_t,
> >      size_t, int, int, int, int);
> > -static int elf32_exec(FILE *, Elf32_Ehdr *, u_long *, int);
> > -static int elf64_exec(FILE *, Elf64_Ehdr *, u_long *, int);
> > +static int elf32_exec(gzFile, Elf32_Ehdr *, u_long *, int);
> > +static int elf64_exec(gzFile, 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);
> > @@ -252,7 +252,7 @@ push_pt_64(void)
> >   * The kernel is loaded to its defined start point as set in the ELF 
> > header.
> >   *
> >   * Parameters:
> > - *  fp: file of a kernel file to load
> > + *  f: file 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
> > @@ -263,7 +263,7 @@ push_pt_64(void)
> >   *  various error codes returned from read(2) or loadelf functions
> >   */
> >  int
> > -loadfile_elf(FILE *fp, struct vm_create_params *vcp,
> > +loadfile_elf(gzFile f, struct vm_create_params *vcp,
> >      struct vcpu_reg_state *vrs, uint32_t bootdev, uint32_t howto,
> >      unsigned int bootdevice)
> >  {
> > @@ -274,17 +274,18 @@ loadfile_elf(FILE *fp, struct vm_create_params *vcp,
> >     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))
> > +   if ((r = gzread(f, &hdr, sizeof(hdr))) == -1 || (size_t)r !=
> > +       sizeof(hdr))
> >             return 1;
> >
> >     memset(&marks, 0, sizeof(marks));
> >     if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
> >         hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
> > -           r = elf32_exec(fp, &hdr.elf32, marks, LOAD_ALL);
> > +           r = elf32_exec(f, &hdr.elf32, marks, LOAD_ALL);
> >             is_i386 = 1;
> >     } else if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
> >         hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
> > -           r = elf64_exec(fp, &hdr.elf64, marks, LOAD_ALL);
> > +           r = elf64_exec(f, &hdr.elf64, marks, LOAD_ALL);
> >     } else
> >             errno = ENOEXEC;
> >
> > @@ -490,7 +491,7 @@ push_stack(uint32_t bootargsz, uint32_t end, uint32_t
> >   * into the guest address space at paddr 'addr'.
> >   *
> >   * Parameters:
> > - *  fd: file descriptor of the kernel image file to read from.
> > + *  f: kernel image file to read from.
> >   *  addr: guest paddr_t to load to
> >   *  sz: number of bytes to load
> >   *
> > @@ -498,10 +499,11 @@ push_stack(uint32_t bootargsz, uint32_t end, uint32_t
> >   *  returns 'sz' if successful, or 0 otherwise.
> >   */
> >  size_t
> > -mread(FILE *fp, paddr_t addr, size_t sz)
> > +mread(gzFile f, paddr_t addr, size_t sz)
> >  {
> >     size_t ct;
> >     size_t i, rd, osz;
> > +   int r;
> >     char buf[PAGE_SIZE];
> >
> >     /*
> > @@ -518,7 +520,7 @@ mread(FILE *fp, paddr_t addr, size_t sz)
> >             else
> >                     ct = sz;
> >
> > -           if (fread(buf, 1, ct, fp) != ct) {
> > +           if ((r = gzread(f, buf, ct)) == -1 || (size_t)r != ct) {
> >                     log_warn("%s: error %d in mread", __progname, errno);
> >                     return (0);
> >             }
> > @@ -542,7 +544,7 @@ mread(FILE *fp, paddr_t addr, size_t sz)
> >             else
> >                     ct = PAGE_SIZE;
> >
> > -           if (fread(buf, 1, ct, fp) != ct) {
> > +           if ((r = gzread(f, buf, ct)) == -1 || (size_t)r != ct) {
> >                     log_warn("%s: error %d in mread", __progname, errno);
> >                     return (0);
> >             }
> > @@ -665,12 +667,12 @@ mbcopy(void *src, paddr_t dst, int sz)
> >   *  1 if unsuccessful
> >   */
> >  static int
> > -elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, int flags)
> > +elf64_exec(gzFile f, Elf64_Ehdr *elf, u_long *marks, int flags)
> >  {
> >     Elf64_Shdr *shp;
> >     Elf64_Phdr *phdr;
> >     Elf64_Off off;
> > -   int i;
> > +   int i, r;
> >     size_t sz;
> >     int first;
> >     int havesyms;
> > @@ -680,12 +682,12 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >     sz = elf->e_phnum * sizeof(Elf64_Phdr);
> >     phdr = malloc(sz);
> >
> > -   if (fseeko(fp, (off_t)elf->e_phoff, SEEK_SET) == -1)  {
> > +   if (gzseek(f, (off_t)elf->e_phoff, SEEK_SET) == -1)  {
> >             free(phdr);
> >             return 1;
> >     }
> >
> > -   if (fread(phdr, 1, sz, fp) != sz) {
> > +   if ((r = gzread(f, phdr, sz)) == -1 || (size_t)r != sz) {
> >             free(phdr);
> >             return 1;
> >     }
> > @@ -725,12 +727,12 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >                 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
> >
> >                     /* Read in segment. */
> > -                   if (fseeko(fp, (off_t)phdr[i].p_offset,
> > +                   if (gzseek(f, (off_t)phdr[i].p_offset,
> >                         SEEK_SET) == -1) {
> >                             free(phdr);
> >                             return 1;
> >                     }
> > -                   if (mread(fp, phdr[i].p_paddr, phdr[i].p_filesz) !=
> > +                   if (mread(f, phdr[i].p_paddr, phdr[i].p_filesz) !=
> >                         phdr[i].p_filesz) {
> >                             free(phdr);
> >                             return 1;
> > @@ -770,14 +772,14 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >             maxp += sizeof(Elf64_Ehdr);
> >
> >     if (flags & (LOAD_SYM | COUNT_SYM)) {
> > -           if (fseeko(fp, (off_t)elf->e_shoff, SEEK_SET) == -1)  {
> > +           if (gzseek(f, (off_t)elf->e_shoff, SEEK_SET) == -1)  {
> >                     warn("lseek section headers");
> >                     return 1;
> >             }
> >             sz = elf->e_shnum * sizeof(Elf64_Shdr);
> >             shp = malloc(sz);
> >
> > -           if (fread(shp, 1, sz, fp) != sz) {
> > +           if ((r = gzread(f, shp, sz)) == -1 || (size_t)r != sz) {
> >                     free(shp);
> >                     return 1;
> >             }
> > @@ -787,13 +789,14 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >
> >             size_t shstrsz = shp[elf->e_shstrndx].sh_size;
> >             char *shstr = malloc(shstrsz);
> > -           if (fseeko(fp, (off_t)shp[elf->e_shstrndx].sh_offset,
> > +           if (gzseek(f, (off_t)shp[elf->e_shstrndx].sh_offset,
> >                 SEEK_SET) == -1) {
> >                     free(shstr);
> >                     free(shp);
> >                     return 1;
> >             }
> > -           if (fread(shstr, 1, shstrsz, fp) != shstrsz) {
> > +           if ((r = gzread(f, shstr, shstrsz)) == -1 || (size_t)r !=
> > +               shstrsz) {
> >                     free(shstr);
> >                     free(shp);
> >                     return 1;
> > @@ -816,13 +819,13 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >                         !strcmp(shstr + shp[i].sh_name, ".debug_line") ||
> >                         !strcmp(shstr + shp[i].sh_name, ELF_CTF)) {
> >                             if (havesyms && (flags & LOAD_SYM)) {
> > -                                   if (fseeko(fp, (off_t)shp[i].sh_offset,
> > +                                   if (gzseek(f, (off_t)shp[i].sh_offset,
> >                                         SEEK_SET) == -1) {
> >                                             free(shstr);
> >                                             free(shp);
> >                                             return 1;
> >                                     }
> > -                                   if (mread(fp, maxp,
> > +                                   if (mread(f, maxp,
> >                                         shp[i].sh_size) != shp[i].sh_size) {
> >                                             free(shstr);
> >                                             free(shp);
> > @@ -875,7 +878,7 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >   * This function is used for 32 bit kernels.
> >   *
> >   * Parameters:
> > - *  fd: file descriptor of the kernel to load
> > + *  f: kernel file to load
> >   *  elf: ELF header of the kernel
> >   *  marks: array to store the offsets of various kernel structures
> >   *      (start, bss, etc)
> > @@ -887,12 +890,12 @@ elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, i
> >   *  1 if unsuccessful
> >   */
> >  static int
> > -elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long *marks, int flags)
> > +elf32_exec(gzFile f, Elf32_Ehdr *elf, u_long *marks, int flags)
> >  {
> >     Elf32_Shdr *shp;
> >     Elf32_Phdr *phdr;
> >     Elf32_Off off;
> > -   int i;
> > +   int i, r;
> >     size_t sz;
> >     int first;
> >     int havesyms;
> > @@ -902,12 +905,12 @@ elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long *marks, i
> >     sz = elf->e_phnum * sizeof(Elf32_Phdr);
> >     phdr = malloc(sz);
> >
> > -   if (fseeko(fp, (off_t)elf->e_phoff, SEEK_SET) == -1)  {
> > +   if (gzseek(f, (off_t)elf->e_phoff, SEEK_SET) == -1) {
> >             free(phdr);
> >             return 1;
> >     }
> >
> > -   if (fread(phdr, 1, sz, fp) != sz) {
> > +   if ((r = gzread(f, phdr, sz)) == -1 || (size_t)r != sz) {
> >             free(phdr);
> >             return 1;
> >     }
> > @@ -947,12 +950,12 @@ elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long *marks, i
> >                 (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
> >
> >                     /* Read in segment. */
> > -                   if (fseeko(fp, (off_t)phdr[i].p_offset,
> > +                   if (gzseek(f, (off_t)phdr[i].p_offset,
> >                         SEEK_SET) == -1) {
> >                             free(phdr);
> >                             return 1;
> >                     }
> > -                   if (mread(fp, phdr[i].p_paddr, phdr[i].p_filesz) !=
> > +                   if (mread(f, phdr[i].p_paddr, phdr[i].p_filesz) !=
> >                         phdr[i].p_filesz) {
> >                             free(phdr);
> >                             return 1;
> > @@ -992,14 +995,14 @@ elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long *marks, i
> >             maxp += sizeof(Elf32_Ehdr);
> >
> >     if (flags & (LOAD_SYM | COUNT_SYM)) {
> > -           if (fseeko(fp, (off_t)elf->e_shoff, SEEK_SET) == -1)  {
> > +           if (gzseek(f, (off_t)elf->e_shoff, SEEK_SET) == -1) {
> >                     warn("lseek section headers");
> >                     return 1;
> >             }
> >             sz = elf->e_shnum * sizeof(Elf32_Shdr);
> >             shp = malloc(sz);
> >
> > -           if (fread(shp, 1, sz, fp) != sz) {
> > +           if ((r = gzread(f, shp, sz)) == -1 || (size_t)r != sz) {
> >                     free(shp);
> >                     return 1;
> >             }
> > @@ -1009,13 +1012,14 @@ elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long 
> > *marks, i
> >
> >             size_t shstrsz = shp[elf->e_shstrndx].sh_size;
> >             char *shstr = malloc(shstrsz);
> > -           if (fseeko(fp, (off_t)shp[elf->e_shstrndx].sh_offset,
> > +           if (gzseek(f, (off_t)shp[elf->e_shstrndx].sh_offset,
> >                 SEEK_SET) == -1) {
> >                     free(shstr);
> >                     free(shp);
> >                     return 1;
> >             }
> > -           if (fread(shstr, 1, shstrsz, fp) != shstrsz) {
> > +           if ((r = gzread(f, shstr, shstrsz)) == -1 || (size_t)r !=
> > +               shstrsz) {
> >                     free(shstr);
> >                     free(shp);
> >                     return 1;
> > @@ -1037,13 +1041,13 @@ elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long 
> > *marks, i
> >                         shp[i].sh_type == SHT_STRTAB ||
> >                         !strcmp(shstr + shp[i].sh_name, ".debug_line")) {
> >                             if (havesyms && (flags & LOAD_SYM)) {
> > -                                   if (fseeko(fp, (off_t)shp[i].sh_offset,
> > +                                   if (gzseek(f, (off_t)shp[i].sh_offset,
> >                                         SEEK_SET) == -1) {
> >                                             free(shstr);
> >                                             free(shp);
> >                                             return 1;
> >                                     }
> > -                                   if (mread(fp, maxp,
> > +                                   if (mread(f, maxp,
> >                                         shp[i].sh_size) != shp[i].sh_size) {
> >                                             free(shstr);
> >                                             free(shp);
> > blob - e825f203ebbbb6d8c5dab5c1594dc815f92fd867
> > blob + 9afd81b28fc9bfc617fac7d99eb4fe744e906832
> > --- usr.sbin/vmd/vm.c
> > +++ usr.sbin/vmd/vm.c
> > @@ -21,6 +21,7 @@
> >  #include <sys/queue.h>
> >  #include <sys/wait.h>
> >  #include <sys/uio.h>
> > +#include <sys/stat.h>
> >  #include <sys/socket.h>
> >  #include <sys/time.h>
> >  #include <sys/mman.h>
> > @@ -84,7 +85,7 @@ void vcpu_exit_inout(struct vm_run_params *);
> >  int vcpu_exit_eptviolation(struct vm_run_params *);
> >  uint8_t vcpu_exit_pci(struct vm_run_params *);
> >  int vcpu_pic_intr(uint32_t, uint32_t, uint8_t);
> > -int loadfile_bios(FILE *, struct vcpu_reg_state *);
> > +int loadfile_bios(gzFile, off_t, struct vcpu_reg_state *);
> >  int send_vm(int, struct vm_create_params *);
> >  int dump_send_header(int);
> >  int dump_vmr(int , struct vm_mem_range *);
> > @@ -212,7 +213,8 @@ static const struct vcpu_reg_state vcpu_init_flat16 =
> >   * directly into memory.
> >   *
> >   * Parameters:
> > - *  fp: file of a kernel file to load
> > + *  f: BIOS file to load
> > + *  size: size of the image
> >   *  (out) vrs: register state to set on init for this kernel
> >   *
> >   * Return values:
> > @@ -220,16 +222,15 @@ static const struct vcpu_reg_state vcpu_init_flat16 =
> >   *  various error codes returned from read(2) or loadelf functions
> >   */
> >  int
> > -loadfile_bios(FILE *fp, struct vcpu_reg_state *vrs)
> > +loadfile_bios(gzFile f, off_t size, struct vcpu_reg_state *vrs)
> >  {
> > -   off_t    size, off;
> > +   off_t    off;
> >
> >     /* Set up a "flat 16 bit" register state for BIOS */
> >     memcpy(vrs, &vcpu_init_flat16, sizeof(*vrs));
> >
> > -   /* Get the size of the BIOS image and seek to the beginning */
> > -   if (fseeko(fp, 0, SEEK_END) == -1 || (size = ftello(fp)) == -1 ||
> > -       fseeko(fp, 0, SEEK_SET) == -1)
> > +   /* Seek to the beginning of the BIOS image */
> > +   if (gzseek(f, 0, SEEK_SET) == -1)
> >             return (-1);
> >
> >     /* The BIOS image must end at 1M */
> > @@ -237,7 +238,7 @@ loadfile_bios(FILE *fp, struct vcpu_reg_state *vrs)
> >             return (-1);
> >
> >     /* Read BIOS image into memory */
> > -   if (mread(fp, off, size) != (size_t)size) {
> > +   if (mread(f, off, size) != (size_t)size) {
> >             errno = EIO;
> >             return (-1);
> >     }
> > @@ -277,10 +278,11 @@ start_vm(struct vmd_vm *vm, int fd)
> >     struct vcpu_reg_state    vrs;
> >     int                      nicfds[VMM_MAX_NICS_PER_VM];
> >     int                      ret;
> > -   FILE                    *fp;
> > +   gzFile                   f;
> >     struct vmboot_params     vmboot;
> >     size_t                   i;
> >     struct vm_rwregs_params  vrp;
> > +   struct stat              sb;
> >
> >     /* Child */
> >     setproctitle("%s", vcp->vcp_name);
> > @@ -332,26 +334,29 @@ 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,
> > +           if ((f = vmboot_open(vm->vm_kernel,
> >                 vm->vm_disks[0], vmc->vmc_diskbases[0],
> >                 vmc->vmc_disktypes[0], &vmboot)) == NULL)
> >                     fatalx("failed to open kernel - exiting");
> >
> >             /* Load kernel image */
> > -           ret = loadfile_elf(fp, vcp, &vrs,
> > +           ret = loadfile_elf(f, vcp, &vrs,
> >                 vmboot.vbp_bootdev, vmboot.vbp_howto, vmc->vmc_bootdevice);
> >
> >             /*
> >              * Try BIOS as a fallback (only if it was provided as an image
> > -            * with vm->vm_kernel and not loaded from the disk)
> > +            * with vm->vm_kernel, was not loaded from the disk, and is
> > +            * not gzipped)
> >              */
> > -           if (ret && errno == ENOEXEC && vm->vm_kernel != -1)
> > -                   ret = loadfile_bios(fp, &vrs);
> > +           if (ret && errno == ENOEXEC && vm->vm_kernel != -1 &&
> > +               gzdirect(f) && (ret = fstat(vm->vm_kernel, &sb)) == 0) {
> > +                   ret = loadfile_bios(f, sb.st_size, &vrs);
> > +           }
> >
> >             if (ret)
> >                     fatal("failed to load kernel or BIOS - exiting");
> >
> > -           vmboot_close(fp, &vmboot);
> > +           vmboot_close(f, &vmboot);
> >     }
> >
> >     if (vm->vm_kernel != -1)
> > blob - 349635fc33db2552a87ce87a66fa5289f6b345bd
> > blob + 611b1afc99bdba1dd2a94eb4be99496374a9ad91
> > --- usr.sbin/vmd/vmboot.c
> > +++ usr.sbin/vmd/vmboot.c
> > @@ -32,6 +32,7 @@
> >  #include <fcntl.h>
> >  #include <err.h>
> >  #include <vis.h>
> > +#include <zlib.h>
> >
> >  #include "vmd.h"
> >  #include "vmboot.h"
> > @@ -384,7 +385,7 @@ vmboot_loadfile(struct open_file *f, char *file, size_
> >     return (p);
> >  }
> >
> > -FILE *
> > +gzFile
> >  vmboot_open(int kernel_fd, int *disk_fd, int nfd, unsigned int disk_type,
> >      struct vmboot_params *vmboot)
> >  {
> > @@ -402,7 +403,7 @@ vmboot_open(int kernel_fd, int *disk_fd, int nfd, unsi
> >
> >     /* First open kernel directly if specified by fd */
> >     if (kernel_fd != -1)
> > -           return (fdopen(kernel_fd, "r"));
> > +           return (gzdopen(kernel_fd, "r"));
> >
> >     if (disk_fd == NULL || nfd < 1)
> >             return (NULL);
> > @@ -481,19 +482,19 @@ vmboot_open(int kernel_fd, int *disk_fd, int nfd, unsi
> >                 vmboot->vbp_device, vmboot->vbp_image);
> >     }
> >
> > -   return (fp);
> > +   return (gzdopen(fileno(fp), "r"));
> >    fail:
> > -   vmboot_close(fp, vmboot);
> > +   vmboot_close(NULL, vmboot);
> >     return (NULL);
> >  }
> >
> >  void
> > -vmboot_close(FILE *fp, struct vmboot_params *vmboot)
> > +vmboot_close(gzFile f, struct vmboot_params *vmboot)
> >  {
> >     struct virtio_backing   *vfp = vmboot->vbp_arg;
> >
> > -   if (fp != NULL)
> > -           fclose(fp);
> > +   if (f != NULL)
> > +           gzclose(f);
> >     if (vfp != NULL)
> >             vfp->close(vfp->p, 1);
> >     free(vmboot->vbp_arg);
> > blob - 325d40d1ace0714e86d20fac20f3eaabd406d721
> > blob + 843293bc7284fe4e623526c4049a7be5b9a37541
> > --- usr.sbin/vmd/vmd.h
> > +++ usr.sbin/vmd/vmd.h
> > @@ -30,6 +30,7 @@
> >  #include <limits.h>
> >  #include <stdio.h>
> >  #include <pthread.h>
> > +#include <zlib.h>
> >
> >  #include "proc.h"
> >
> > @@ -475,8 +476,8 @@ int      config_getif(struct privsep *, struct imsg *);
> >  int         config_getcdrom(struct privsep *, struct imsg *);
> >
> >  /* vmboot.c */
> > -FILE       *vmboot_open(int, int *, int, unsigned int, struct 
> > vmboot_params *);
> > -void        vmboot_close(FILE *, struct vmboot_params *);
> > +gzFile     vmboot_open(int, int *, int, unsigned int, struct vmboot_params 
> > *);
> > +void       vmboot_close(gzFile, struct vmboot_params *);
> >
> >  /* parse.y */
> >  int         parse_config(const char *);
> 
> 
> --
> -Dave Voutila
> 

Reply via email to