From ea4ecf2bb479b63c70c3a380af864823d883d2dd Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 24 Feb 2012 17:04:57 +0200 Subject: [PATCH] kvm tools, seabios: Add "--firmware" option to "vm run" 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 Cc: Yang Bai Cc: Matt Evans Cc: Ron Minnich Cc: Anthony Liguori Cc: John Floren Cc: Sasha Levin Cc: Asias He Cc: Ingo Molnar Signed-off-by: Pekka Enberg --- tools/kvm/Makefile | 2 ++ tools/kvm/builtin-run.c | 32 ++++++++++++++++--------- tools/kvm/include/kvm/kvm.h | 1 + tools/kvm/powerpc/boot.c | 8 +++++++ tools/kvm/x86/boot.c | 41 ++++++++++++++++++++++++++++++++ tools/kvm/x86/include/kvm/bios.h | 3 ++- 6 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 tools/kvm/powerpc/boot.c create mode 100644 tools/kvm/x86/boot.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index cfa554736764..0a9c2ccfc000 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -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 diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c index 466169e0d872..6acc490e0328 100644 --- a/tools/kvm/builtin-run.c +++ b/tools/kvm/builtin-run.c @@ -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++) { diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h index 78701189d8c9..d4cfcefc1150 100644 --- a/tools/kvm/include/kvm/kvm.h +++ b/tools/kvm/include/kvm/kvm.h @@ -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 index 000000000000..2557fc077e42 --- /dev/null +++ b/tools/kvm/powerpc/boot.c @@ -0,0 +1,8 @@ +#include "kvm/kvm.h" + +#include + +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 index 000000000000..93838240e938 --- /dev/null +++ b/tools/kvm/x86/boot.c @@ -0,0 +1,41 @@ +#include "kvm/kvm.h" + +#include "kvm/util.h" + +#include +#include +#include +#include + +#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; +} diff --git a/tools/kvm/x86/include/kvm/bios.h b/tools/kvm/x86/include/kvm/bios.h index de569bc108a8..9d677ae9da28 100644 --- a/tools/kvm/x86/include/kvm/bios.h +++ b/tools/kvm/x86/include/kvm/bios.h @@ -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 -- 2.39.5