]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools, seabios: Add "--firmware" option to "vm run"
authorPekka Enberg <penberg@kernel.org>
Fri, 24 Feb 2012 15:04:57 +0000 (17:04 +0200)
committerPekka Enberg <penberg@kernel.org>
Fri, 24 Feb 2012 17:56:51 +0000 (19:56 +0200)
This patch adds a "--firmware" command line option to "vm run". You can use
this to try to boot with SeaBIOS, for example:

  ./vm run --firmware=/usr/share/seabios/bios.bin \
 --disk $HOME/images/debian_lenny_amd64_standard.qcow2

This doesn't boot yet for obvious reasons but at least people can now start to
play with external BIOS images easily.

Acked-by Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Yang Bai <hamo.by@gmail.com>
Cc: Matt Evans <matt@ozlabs.org>
Cc: Ron Minnich <rminnich@gmail.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: John Floren <john@jfloren.net>
Cc: Sasha Levin <levinsasha928@gmail.com>
Cc: Asias He <asias.hejun@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/Makefile
tools/kvm/builtin-run.c
tools/kvm/include/kvm/kvm.h
tools/kvm/powerpc/boot.c [new file with mode: 0644]
tools/kvm/x86/boot.c [new file with mode: 0644]
tools/kvm/x86/include/kvm/bios.h

index cfa554736764255dbbc3ab36137721c03161a4ca..0a9c2ccfc000a6a0f6a7d3039321e03a186bbb6c 100644 (file)
@@ -113,6 +113,7 @@ LIBFDT_OBJS = $(patsubst %,../../scripts/dtc/libfdt/%,$(LIBFDT_SRC))
 #x86
 ifeq ($(ARCH),x86)
        DEFINES += -DCONFIG_X86
+       OBJS    += x86/boot.o
        OBJS    += x86/cpuid.o
        OBJS    += x86/interrupt.o
        OBJS    += x86/ioport.o
@@ -129,6 +130,7 @@ endif
 # POWER/ppc:  Actually only support ppc64 currently.
 ifeq ($(uname_M), ppc64)
        DEFINES += -DCONFIG_PPC
+       OBJS    += powerpc/boot.o
        OBJS    += powerpc/ioport.o
        OBJS    += powerpc/irq.o
        OBJS    += powerpc/kvm.o
index 466169e0d87256d5ed96f77369b3e12cbcf8defd..6acc490e032803a27e82201fef1559f71a5ef345 100644 (file)
@@ -76,6 +76,7 @@ static const char *kernel_cmdline;
 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;
@@ -458,6 +459,8 @@ static const struct option options[] = {
                        "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",
@@ -1110,14 +1113,16 @@ static int kvm_cmd_run_init(int argc, const char **argv)
        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();
 
@@ -1218,10 +1223,15 @@ static int kvm_cmd_run_init(int argc, const char **argv)
 
        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++) {
index 78701189d8c9c04730850bda8de86794c1c1996d..d4cfcefc1150802434c4433f35918689caa8a2af 100644 (file)
@@ -39,6 +39,7 @@ int kvm__recommended_cpus(struct kvm *kvm);
 int kvm__max_cpus(struct kvm *kvm);
 void kvm__init_ram(struct kvm *kvm);
 int kvm__exit(struct kvm *kvm);
+bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename);
 bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
                        const char *initrd_filename, const char *kernel_cmdline, u16 vidmode);
 void kvm__start_timer(struct kvm *kvm);
diff --git a/tools/kvm/powerpc/boot.c b/tools/kvm/powerpc/boot.c
new file mode 100644 (file)
index 0000000..2557fc0
--- /dev/null
@@ -0,0 +1,8 @@
+#include "kvm/kvm.h"
+
+#include <stdbool.h>
+
+bool kvm__load_firmware(struct kvm *kvm, const char *firmware_filename)
+{
+       return false;
+}
diff --git a/tools/kvm/x86/boot.c b/tools/kvm/x86/boot.c
new file mode 100644 (file)
index 0000000..9383824
--- /dev/null
@@ -0,0 +1,41 @@
+#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;
+}
index de569bc108a8e3b43a0debbb752645c2c660e6d1..9d677ae9da283cfc7834e88af6906029f23b99be 100644 (file)
@@ -26,8 +26,9 @@
 
 #define E820_MAP_START                 EBDA_START
 
-#define MB_BIOS_BEGIN                  0x000f0000
+#define MB_BIOS_BEGIN                  0x000e0000
 #define MB_BIOS_END                    0x000fffff
+#define MB_BIOS_SIZE                   (MB_BIOS_END - MB_BIOS_BEGIN + 1)
 
 #define VGA_RAM_BEGIN                  0x000a0000
 #define VGA_RAM_END                    0x000bffff