static const char *kernel_filename;
static const char *vmlinux_filename;
static const char *initrd_filename;
+static const char *firmware_filename;
static const char *image_filename[MAX_DISK_IMAGES];
static const char *console;
static const char *dev;
"Initial RAM disk image"),
OPT_STRING('p', "params", &kernel_cmdline, "params",
"Kernel command line arguments"),
+ OPT_STRING('f', "firmware", &firmware_filename, "firmware",
+ "Firmware image to boot in virtual machine"),
OPT_GROUP("Networking options:"),
OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params",
printf(" # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME,
kernel_filename, ram_size / 1024 / 1024, nrcpus, guest_name);
- if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename,
- real_cmdline, vidmode))
- die("unable to load kernel %s", kernel_filename);
+ if (!firmware_filename) {
+ if (!kvm__load_kernel(kvm, kernel_filename,
+ initrd_filename, real_cmdline, vidmode))
+ die("unable to load kernel %s", kernel_filename);
- kvm->vmlinux = vmlinux_filename;
- r = symbol_init(kvm);
- if (r < 0)
- pr_debug("symbol_init() failed with error %d\n", r);
+ kvm->vmlinux = vmlinux_filename;
+ r = symbol_init(kvm);
+ if (r < 0)
+ pr_debug("symbol_init() failed with error %d\n", r);
+ }
ioport__setup_arch();
kvm__start_timer(kvm);
- kvm__arch_setup_firmware(kvm);
- if (r < 0) {
- pr_err("kvm__arch_setup_firmware() failed with error %d\n", r);
- goto fail;
+ if (firmware_filename) {
+ if (!kvm__load_firmware(kvm, firmware_filename))
+ die("unable to load firmware image %s: %s", firmware_filename, strerror(errno));
+ } else {
+ kvm__arch_setup_firmware(kvm);
+ if (r < 0) {
+ pr_err("kvm__arch_setup_firmware() failed with error %d\n", r);
+ goto fail;
+ }
}
for (i = 0; i < nrcpus; i++) {
--- /dev/null
+#include "kvm/kvm.h"
+
+#include "kvm/util.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <fcntl.h>
+
+#define BIOS_SELECTOR 0xf000
+#define BIOS_IP 0xfff0
+#define BIOS_SP 0x8000
+
+bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename)
+{
+ struct stat st;
+ void *p;
+ int fd;
+ int nr;
+
+ fd = open(firmware_filename, O_RDONLY);
+ if (fd < 0)
+ return false;
+
+ if (fstat(fd, &st))
+ return false;
+
+ if (st.st_size > MB_BIOS_SIZE)
+ die("firmware image %s is too big to fit in memory (%lu KB).\n", firmware_filename, st.st_size / 1024);
+
+ p = guest_flat_to_host(kvm, MB_BIOS_BEGIN);
+
+ while ((nr = read(fd, p, st.st_size)) > 0)
+ p += nr;
+
+ kvm->boot_selector = BIOS_SELECTOR;
+ kvm->boot_ip = BIOS_IP;
+ kvm->boot_sp = BIOS_SP;
+
+ return true;
+}