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). 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
