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,
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));
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".
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.
after getting and extracting seabios sources, cd to the source directory.
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, ... };
- 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.
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.
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