The following set of patches add TPM and Trusted Computing support to SeaBIOS.
In particular the patches add:
- a TPM driver for the Qemu's TPM TIS emulation (not yet in Qemu git)
- ACPI support for the TPM device (SSDT table)
- ACPI support for measurement logging (TCPA table)
- Support for initialzation of the TPM
- Support for the TCG BIOS extensions (1ah handler [ah = 0xbb])
(used by trusted grub; http://trousers.sourceforge.net/grub.html)
- Static Root of Trusted for Measurement (SRTM) support
- Support for S3 resume (sends command to TPM upon resume)
- TPM-specific menu for controlling aspects of the TPM
- [An optional test suite for the TIS interface]
All implementations necessarily follow specifications.
When all patches are applied the following services are available
- SSDT ACPI table for TPM support
- initialization of the TPM upon VM start and S3 resume
- Static root of trust for measurements (SRTM) that measures (some) data
of SeaBIOS in TCPA ACPI table
- 1ah interrupt handler offering APIs for measuring and sending commands to
the TPM (trusted grub uses them)
- User menu for controlling aspects of the state of the TPM
v3:
- some nits here and there
- calling timer_setup now after S3 resume
v2:
- following Kevin's comment
- refactoring code so that every patch compiles
Regards,
Stefan
The following set of patches add TPM and Trusted Computing support to SeaBIOS.
In particular the patches add:
- a TPM driver for the Qemu's TPM TIS emulation (not yet in Qemu git)
- ACPI support for the TPM device (SSDT table)
- ACPI support for measurement logging (TCPA table)
- Support for initialzation of the TPM
- Support for the TCG BIOS extensions (1ah handler [ah = 0xbb])
(used by trusted grub; http://trousers.sourceforge.net/grub.html)
- Static Root of Trusted for Measurement (SRTM) support
- Support for S3 resume (sends command to TPM upon resume)
- TPM-specific menu for controlling aspects of the TPM
- [An optional test suite for the TIS interface]
All implementations necessarily follow specifications.
- v2:
- following Kevin's comment
- refactoring code so that every patch compiles
Regards,
Stefan
The following set of patches add TPM and Trusted Computing support to SeaBIOS.
In particular the patches add:
- a TPM driver for the Qemu's TPM TIS emulation (not yet in Qemu git)
- ACPI support for the TPM device (SSDT table)
- ACPI support for measurement logging (TCPA table)
- Support for initialzation of the TPM
- Support for the TCG BIOS extensions (1ah handler [ah = 0xbb])
(used by trusted grub; http://trousers.sourceforge.net/grub.html)
- Static Root of Trusted for Measurement (SRTM) support
- Support for S3 resume (sends command to TPM upon resume)
- TPM-specific menu for controlling aspects of the TPM
- [An optional test suite for the TIS interface]
All implementations necessarily follow specifications.
Regards,
Stefan
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".
>
> 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
>
--
yamahata