/* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
-/* $OpenBSD: loadfile_elf.c,v 1.37 2021/03/19 09:29:33 kn Exp $ */
+/* $OpenBSD: loadfile_elf.c,v 1.38 2021/04/05 18:09:48 dv Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
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);
static size_t push_stack(uint32_t, uint32_t);
*
* Return values:
* 0 if successful
- * various error codes returned from read(2) or loadelf functions
+ * various error codes returned from gzread(3) or loadelf functions
*/
int
-loadfile_elf(FILE *fp, struct vm_create_params *vcp, struct vcpu_reg_state *vrs)
+loadfile_elf(gzFile fp, struct vm_create_params *vcp,
+ struct vcpu_reg_state *vrs)
{
int r, is_i386 = 0;
uint32_t bootargsz;
u_long marks[MARK_MAX];
bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1];
- if ((r = fread(&hdr, 1, sizeof(hdr), fp)) != sizeof(hdr))
+ if ((r = gzread(fp, &hdr, sizeof(hdr))) != sizeof(hdr))
return 1;
memset(&marks, 0, sizeof(marks));
* into the guest address space at paddr 'addr'.
*
* Parameters:
- * fd: file descriptor of the kernel image file to read from.
+ * fp: kernel image file to read from.
* addr: guest paddr_t to load to
* sz: number of bytes to load
*
* returns 'sz' if successful, or 0 otherwise.
*/
size_t
-mread(FILE *fp, paddr_t addr, size_t sz)
+mread(gzFile fp, paddr_t addr, size_t sz)
{
size_t ct;
size_t i, rd, osz;
else
ct = sz;
- if (fread(buf, 1, ct, fp) != ct) {
+ if ((size_t)gzread(fp, buf, ct) != ct) {
log_warn("%s: error %d in mread", __progname, errno);
return (0);
}
else
ct = PAGE_SIZE;
- if (fread(buf, 1, ct, fp) != ct) {
+ if ((size_t)gzread(fp, buf, ct) != ct) {
log_warn("%s: error %d in mread", __progname, errno);
return (0);
}
/*
* elf64_exec
*
- * Load the kernel indicated by 'fd' into the guest physical memory
+ * Load the kernel indicated by 'fp' into the guest physical memory
* space, at the addresses defined in the ELF header.
*
* This function is used for 64 bit kernels.
*
* Parameters:
- * fd: file descriptor of the kernel to load
+ * fp: kernel image file to load
* elf: ELF header of the kernel
* marks: array to store the offsets of various kernel structures
* (start, bss, etc)
* 1 if unsuccessful
*/
static int
-elf64_exec(FILE *fp, Elf64_Ehdr *elf, u_long *marks, int flags)
+elf64_exec(gzFile fp, Elf64_Ehdr *elf, u_long *marks, int flags)
{
Elf64_Shdr *shp;
Elf64_Phdr *phdr;
sz = elf->e_phnum * sizeof(Elf64_Phdr);
phdr = malloc(sz);
- if (fseeko(fp, (off_t)elf->e_phoff, SEEK_SET) == -1) {
+ if (gzseek(fp, (off_t)elf->e_phoff, SEEK_SET) == -1) {
free(phdr);
return 1;
}
- if (fread(phdr, 1, sz, fp) != sz) {
+ if ((size_t)gzread(fp, phdr, sz) != sz) {
free(phdr);
return 1;
}
(IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
/* Read in segment. */
- if (fseeko(fp, (off_t)phdr[i].p_offset,
+ if (gzseek(fp, (off_t)phdr[i].p_offset,
SEEK_SET) == -1) {
free(phdr);
return 1;
maxp += sizeof(Elf64_Ehdr);
if (flags & (LOAD_SYM | COUNT_SYM)) {
- if (fseeko(fp, (off_t)elf->e_shoff, SEEK_SET) == -1) {
- warn("lseek section headers");
+ if (gzseek(fp, (off_t)elf->e_shoff, SEEK_SET) == -1) {
+ warn("gzseek section headers");
return 1;
}
sz = elf->e_shnum * sizeof(Elf64_Shdr);
shp = malloc(sz);
- if (fread(shp, 1, sz, fp) != sz) {
+ if ((size_t)gzread(fp, shp, sz) != sz) {
free(shp);
return 1;
}
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(fp, (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 ((size_t)gzread(fp, shstr, shstrsz) != shstrsz) {
free(shstr);
free(shp);
return 1;
!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(fp, (off_t)shp[i].sh_offset,
SEEK_SET) == -1) {
free(shstr);
free(shp);
/*
* elf32_exec
*
- * Load the kernel indicated by 'fd' into the guest physical memory
+ * Load the kernel indicated by 'fp' into the guest physical memory
* space, at the addresses defined in the ELF header.
*
* This function is used for 32 bit kernels.
*
* Parameters:
- * fd: file descriptor of the kernel to load
+ * fp: kernel image file to load
* elf: ELF header of the kernel
* marks: array to store the offsets of various kernel structures
* (start, bss, etc)
* 1 if unsuccessful
*/
static int
-elf32_exec(FILE *fp, Elf32_Ehdr *elf, u_long *marks, int flags)
+elf32_exec(gzFile fp, Elf32_Ehdr *elf, u_long *marks, int flags)
{
Elf32_Shdr *shp;
Elf32_Phdr *phdr;
sz = elf->e_phnum * sizeof(Elf32_Phdr);
phdr = malloc(sz);
- if (fseeko(fp, (off_t)elf->e_phoff, SEEK_SET) == -1) {
+ if (gzseek(fp, (off_t)elf->e_phoff, SEEK_SET) == -1) {
free(phdr);
return 1;
}
- if (fread(phdr, 1, sz, fp) != sz) {
+ if ((size_t)gzread(fp, phdr, sz) != sz) {
free(phdr);
return 1;
}
(IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {
/* Read in segment. */
- if (fseeko(fp, (off_t)phdr[i].p_offset,
+ if (gzseek(fp, (off_t)phdr[i].p_offset,
SEEK_SET) == -1) {
free(phdr);
return 1;
maxp += sizeof(Elf32_Ehdr);
if (flags & (LOAD_SYM | COUNT_SYM)) {
- if (fseeko(fp, (off_t)elf->e_shoff, SEEK_SET) == -1) {
+ if (gzseek(fp, (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 ((size_t)gzread(fp, shp, sz) != sz) {
free(shp);
return 1;
}
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(fp, (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 ((size_t)gzread(fp, shstr, shstrsz) != shstrsz) {
free(shstr);
free(shp);
return 1;
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(fp, (off_t)shp[i].sh_offset,
SEEK_SET) == -1) {
free(shstr);
free(shp);
-/* $OpenBSD: vm.c,v 1.61 2021/03/29 23:37:01 dv Exp $ */
+/* $OpenBSD: vm.c,v 1.62 2021/04/05 18:09:48 dv Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
#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>
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 *);
*
* Parameters:
* fp: file of a kernel file to load
+ * size: uncompressed size of the image
* (out) vrs: register state to set on init for this kernel
*
* Return values:
* various error codes returned from read(2) or loadelf functions
*/
int
-loadfile_bios(FILE *fp, struct vcpu_reg_state *vrs)
+loadfile_bios(gzFile fp, 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(fp, 0, SEEK_SET) == -1)
return (-1);
/* The BIOS image must end at 1M */
struct vcpu_reg_state vrs;
int nicfds[VMM_MAX_NICS_PER_VM];
int ret;
- FILE *fp;
+ gzFile fp;
size_t i;
struct vm_rwregs_params vrp;
+ struct stat sb;
/* Child */
setproctitle("%s", vcp->vcp_name);
memcpy(&vrs, &vcpu_init_flat64, sizeof(vrs));
/* Find and open kernel image */
- if ((fp = fdopen(vm->vm_kernel, "r")) == NULL)
+ if ((fp = gzdopen(vm->vm_kernel, "r")) == NULL)
fatalx("failed to open kernel - exiting");
/* Load kernel image */
/*
* 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 and the file is not compressed)
*/
- if (ret && errno == ENOEXEC && vm->vm_kernel != -1)
- ret = loadfile_bios(fp, &vrs);
+ if (ret && errno == ENOEXEC && vm->vm_kernel != -1 &&
+ gzdirect(fp) && (ret = fstat(vm->vm_kernel, &sb)) == 0)
+ ret = loadfile_bios(fp, sb.st_size, &vrs);
if (ret)
fatal("failed to load kernel or BIOS - exiting");
- if (fp)
- fclose(fp);
+ gzclose(fp);
}
if (vm->vm_kernel != -1)