From patchwork Fri Apr 1 06:52:21 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 89210 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C43B4B6F8A for ; Fri, 1 Apr 2011 17:53:12 +1100 (EST) Received: from localhost ([127.0.0.1]:42949 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q5YEF-0000HM-LW for incoming@patchwork.ozlabs.org; Fri, 01 Apr 2011 02:53:07 -0400 Received: from [140.186.70.92] (port=34857 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q5YDd-0000HF-3g for qemu-devel@nongnu.org; Fri, 01 Apr 2011 02:52:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q5YDb-00072S-Ma for qemu-devel@nongnu.org; Fri, 01 Apr 2011 02:52:28 -0400 Received: from mail.valinux.co.jp ([210.128.90.3]:53625) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q5YDb-000721-4v for qemu-devel@nongnu.org; Fri, 01 Apr 2011 02:52:27 -0400 Received: from ps.local.valinux.co.jp (vagw.valinux.co.jp [210.128.90.14]) by mail.valinux.co.jp (Postfix) with SMTP id D6233188FA; Fri, 1 Apr 2011 15:52:21 +0900 (JST) Received: (nullmailer pid 10689 invoked by uid 1000); Fri, 01 Apr 2011 06:52:21 -0000 Date: Fri, 1 Apr 2011 15:52:21 +0900 From: Isaku Yamahata To: Michael Tokarev Subject: Re: [Qemu-devel] OEM Windows in qemu/kvm again (mini-howto) Message-ID: <20110401065221.GC8401@valinux.co.jp> References: <4D947AD8.5060205@msgid.tls.msk.ru> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <4D947AD8.5060205@msgid.tls.msk.ru> User-Agent: Mutt/1.5.19 (2009-01-05) X-Virus-Scanned: clamav-milter 0.95.2 at va-mail.local.valinux.co.jp X-Virus-Status: Clean X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 210.128.90.3 Cc: Kevin O'Connor , seabios , qemu-devel X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Hi. SLIC table can be fed dynamically by utilize the existing fw_cfg interface. Something like this. (This requires your qemu patch.) This is just for showing the idea. thanks, On Thu, Mar 31, 2011 at 05:00:08PM +0400, Michael Tokarev wrote: > Here's a quick-n-dirty howto about running OEM version > of windows7 or vista in qemu/kvm, assuming you own a > computer with pre-installed OEM version of such operating > system so you have rights to run it there. > > Windows 7 & Vista OEM activation are based on a special > OEM marker in BIOS in a form of one ACPI table named SLIC. > The idea is to take content of that table from your computer > and present it in the virtual machine. > > This table can be taken directly from /sys/firmware/acpi/tables/SLIC > (it's a small binary file), and hopefully qemu will be able > to use that directly (I submitted a patch to do that a few > days ago). > > But there's on caveat still: windows apparently checks not only > the SLIC table/marker, but also verifies that the Vendor ID > fields in SLIC and RSDT tables matches each other. So just > presenting SLIC into a VM isn't enough, one have to modify > at least two fields in RSDT table too. > > And since there's no way currently to do that using qemu > command line, I took another approach and modified seabios > code a bit. Here's a small howto to do that "at home". > > 1) First of all, you need seabios source code appropriate > for your qemu/kvm. See http://www.seabios.org/ for that. > Also you need tools to recompile it, obviously. > > 2) after getting and extracting seabios sources, cd to > the source directory. > > 3) You need to build slic table to be used by a C compiler, > like this: > > xxd -i /sys/firmware/acpi/tables/SLIC | > grep -v len | > sed 's/unsigned char.*/static char SLIC[] = {/' > > src/acpi-slic.hex > > this produces file src/acpi-slic.hex with content like > this: > > static char SLIC[] = { > 0x53, 0x4c, 0x49, 0x43, 0x76, 0x01, ... > }; > > 4) apply the following patch to src/acpi.c: > > ============= cut ============= > --- a/src/acpi.c > +++ b/src/acpi.c > @@ -199,4 +199,9 @@ struct srat_memory_affinity > #include "acpi-dsdt.hex" > > +#define CONFIG_OEM_SLIC > +#ifdef CONFIG_OEM_SLIC > +#include "acpi-slic.hex" > +#endif > + > static void > build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) > @@ -211,4 +216,8 @@ build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) > h->oem_revision = cpu_to_le32(1); > h->asl_compiler_revision = cpu_to_le32(1); > +#ifdef CONFIG_OEM_SLIC > + if (sig == RSDT_SIGNATURE) // only RSDT is checked by win7 & vista > + memcpy(h->oem_id, ((struct acpi_table_header*)SLIC)->oem_id, 14); > +#endif > h->checksum -= checksum(h, len); > } > @@ -627,4 +636,15 @@ acpi_bios_init(void) > ACPI_INIT_TABLE(build_srat()); > > +#ifdef CONFIG_OEM_SLIC > + { void *buf = malloc_high(sizeof(SLIC)); > + if (!buf) > + warn_noalloc(); > + else { > + memcpy(buf, SLIC, sizeof(SLIC)); > + ACPI_INIT_TABLE(buf); > + } > + } > +#endif > + > u16 i, external_tables = qemu_cfg_acpi_additional_tables(); > > ============= cut ============= > > The patch above arranges for your SLIC table to be > included inside the ("virtual") bios (that table does > exactly nothing for the bios itself and for other > system components) and also modifies OEM identification > information in RSDT table to match SLIC table. > > 5) build the bios as usual by issuing `make' in the top > source directory. You'll get out/bios.bin file. > Place it somewhere like /usr/share/qemu/bios-asus.bin > or anywhere like you want. > > 6) and finally, specify that bios file when running your > preinstalled windows: > > qemu -hda /dev/sda -bios /usr/share/qemu/bios-asus.bin > [...other options...] > > (But be careful and choose appropriate boot entry, do > not boot linux itself in your virtual machine :) > > Something like that. This is formed as a quick-n-dirty > howto because there's quite alot of questions lately about > this very stuff (how to run activated windows in qemu), > and I wanted to write an instruction so that less > expirienced people will be able to do that. > > > Kevin, do you remember why this code is present in > acpi.c: > > build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev) > { > memcpy(h->oem_id, CONFIG_APPNAME6, 6); > memcpy(h->oem_table_id, CONFIG_APPNAME4, 4); > memcpy(h->asl_compiler_id, CONFIG_APPNAME4, 4); > memcpy(h->oem_table_id + 4, (void*)&sig, 4); <=== this > > To me it looks like we need another #define, like > CONFIG_APPNAME8, to be used for whole oem_table_id > field. And also, maybe made all this stuff configurable > somehow (starting from the build config in out/autoconf.h > etc) ? > > Thanks! > > /mjt > diff --git a/src/acpi.c b/src/acpi.c index 6428d9c..e0815bd 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -627,6 +627,7 @@ acpi_bios_init(void) ACPI_INIT_TABLE(build_srat()); u16 i, external_tables = qemu_cfg_acpi_additional_tables(); + bool slic = false; for(i = 0; i < external_tables; i++) { u16 len = qemu_cfg_next_acpi_table_len(); @@ -635,7 +636,12 @@ acpi_bios_init(void) warn_noalloc(); continue; } - ACPI_INIT_TABLE(qemu_cfg_next_acpi_table_load(addr, len)); + struct acpi_table_header *header = + qemu_cfg_next_acpi_table_load(addr, len); + if (header->signature == SLIC_SIGNATURE) { + slic = true; + } + ACPI_INIT_TABLE(header); if (tbl_idx == MAX_ACPI_TABLES) { warn_noalloc(); break; @@ -654,6 +660,9 @@ acpi_bios_init(void) memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx); build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1); + if (slic) { + // fix up rsdt->oem_id and check sum + } // Build rsdp pointer table memset(rsdp, 0, sizeof(*rsdp));