Download raw body.
make room for vmd to use 4MB firmware images
SeaBIOS is our current firmware for booting vmd guests (when not direct
booting a kernel image/ramdisk). To continue work on adding EDK2/OVMF
UEFI support, we need to bump our support from 2MB to 4MB because the
resulting firmware is 4MB.
This diff adjusts how we carve out space for firmware images and how we
load them into the lower and upper bios areas. There should be no
regression with existing seabios / vmm-bios firmware images.
ok?
diff refs/heads/master refs/heads/seabios
commit - 7b1f6ebfc4c7f6ea7eccf2eb68f2fe2a321a5266
commit + 1420ebb5a40b7de8dc0b8a85d7c19e2761f62e9d
blob - 925eec31ad1e4d911d195240712e8a5e26c26264
blob + 58825b7b5f99c1c4f8fb3056c36ba150eccdd1ff
--- usr.sbin/vmd/pci.h
+++ usr.sbin/vmd/pci.h
@@ -36,7 +36,7 @@
#define PCI_BAR_TYPE_MMIO 0x1
#define PCI_MMIO_BAR_BASE 0xF0000000ULL
-#define PCI_MMIO_BAR_END 0xFFDFFFFFULL /* 2 MiB below 4 GiB */
+#define PCI_MMIO_BAR_END 0xFFBFFFFFULL /* 4 MiB below 4 GiB */
#define PCI_MAX_PIC_IRQS 10
blob - 52a1c8ce4f09f00e155b0b34c021343d70d93b1c
blob + 11461b3ada7692c0129dbe933d5ab3fb9f51079f
--- usr.sbin/vmd/vmd.h
+++ usr.sbin/vmd/vmd.h
@@ -46,6 +46,7 @@
#define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \
__attribute__((__unused__))
+#define KB(x) (x * 1024UL)
#define MB(x) (x * 1024UL * 1024UL)
#define GB(x) (x * 1024UL * 1024UL * 1024UL)
blob - 6368571bd396c704f8fc7d2668c3a4aa930f77c1
blob + a99a76da8707b8726fbd2297496442b7f9cd4e98
--- usr.sbin/vmd/x86_vm.c
+++ usr.sbin/vmd/x86_vm.c
@@ -190,10 +190,13 @@ create_memory_map(struct vm_create_params *vcp)
vcp->vcp_memranges[1].vmr_type = VM_MEM_RESERVED;
mem_bytes -= len;
- /* If we have less than 2MB remaining, still create a 2nd BIOS area. */
- if (mem_bytes <= MB(2)) {
+ /*
+ * If we have less than 4MB remaining to assign, still create a 2nd
+ * BIOS area.
+ */
+ if (mem_bytes <= MB(4)) {
vcp->vcp_memranges[2].vmr_gpa = PCI_MMIO_BAR_END;
- vcp->vcp_memranges[2].vmr_size = MB(2);
+ vcp->vcp_memranges[2].vmr_size = MB(4);
vcp->vcp_memranges[2].vmr_type = VM_MEM_RESERVED;
vcp->vcp_nmemranges = 3;
return;
@@ -225,7 +228,7 @@ create_memory_map(struct vm_create_params *vcp)
/* Fifth region: 2nd copy of BIOS above MMIO ending at 4GB */
vcp->vcp_memranges[4].vmr_gpa = PCI_MMIO_BAR_END + 1;
- vcp->vcp_memranges[4].vmr_size = MB(2);
+ vcp->vcp_memranges[4].vmr_size = MB(4);
vcp->vcp_memranges[4].vmr_type = VM_MEM_RESERVED;
/* Sixth region: any remainder above 4GB */
@@ -290,35 +293,50 @@ load_firmware(struct vmd_vm *vm, struct vcpu_reg_state
int
loadfile_bios(gzFile fp, off_t size, struct vcpu_reg_state *vrs)
{
- off_t off;
+ off_t off = 0;
+ size_t lower_sz = size;
- /* Set up a "flat 16 bit" register state for BIOS */
+ /*
+ * While a 15 byte firmware is most likely useless, given the
+ * reset vector on a PC is 15 bytes below 0xFFFFF, make sure
+ * we will at least align to that boundary.
+ */
+ if (size < 15) {
+ log_warnx("bios image too small");
+ return (-1);
+ }
+
+ /* Assumptions elsewhere in memory layout limit to 4 MiB. */
+ if (size > (off_t)MB(4)) {
+ log_warnx("bios image too large (> 4 MiB)");
+ return (-1);
+ }
+
+ /* Set up a "flat 16 bit" register state for BIOS. */
memcpy(vrs, &vcpu_init_flat16, sizeof(*vrs));
- /* Seek to the beginning of the BIOS image */
- if (gzseek(fp, 0, SEEK_SET) == -1)
+ /* Read a full copy into BIOS area ending at 4 GiB. */
+ if (gzrewind(fp) == -1)
return (-1);
- /* The BIOS image must end at 1MB */
- if ((off = MB(1) - size) < 0)
- return (-1);
-
- /* Read BIOS image into memory */
- if (mread(fp, off, size) != (size_t)size) {
- errno = EIO;
- return (-1);
- }
-
- if (gzseek(fp, 0, SEEK_SET) == -1)
- return (-1);
-
- /* Read a second BIOS copy into memory ending at 4GB */
off = GB(4) - size;
if (mread(fp, off, size) != (size_t)size) {
errno = EIO;
return (-1);
}
+ /* Copy the last 128K into the lower BIOS area ending at 1 MiB. */
+ if (gzrewind(fp) == -1)
+ return (-1);
+
+ lower_sz = MIN((off_t)KB(128), size);
+ if (gzseek(fp, size - lower_sz, SEEK_SET) == -1)
+ return (-1);
+
+ off = MB(1) - lower_sz;
+ if (mread(fp, off, lower_sz) != lower_sz)
+ return (-1);
+
log_debug("%s: loaded BIOS image", __func__);
return (0);
make room for vmd to use 4MB firmware images