### Overview ### The TPM passthrough feature allow a developer to test TPM functionalities, like Measure Boot, without the need to tamper with critical parts of the host machine, ie. bootloader. It has been implemented to the x86 architecture and have the same interface that is provided to PC machines: TPM TIS.
With the growing of use of the ARM server machines, also comes the need to reuse the same security features that are present in the in the PC server environment. So comes the need to use TPM devices in the ARM architecture. This patchset provides a new frontend to the QEMU TPM passthrough with an interface suitable to communicate with an ARM based machine. ### Technical details ### The TPM devices on the PC architecture are integrated in a way that the interface to it is made using an abstraction layer provided by the BIOS/UFI firmware. That interface is not available to ARM machines, therefore a new QEMU front end with a more suitable interface needed to be developed. The options based on the available TPM devices in the market were I2C and SPI. To make the choice, we look into the supported TPM drivers available to ARM architecture in the Linux Kernel. One of the simplest drivers was the ATMEL I2C TPM AT97SC3204T, so that was our target for the emulation. We created a file called tpm_i2c_atmel.c based on the already available tpm_tis.c, registering as a I2C_SLAVE_CLASS and calling the tpm_backend functions. One of the problems we had to address is regarding the behavior of the ATMEL I2C TPM AT97SC3204T Linux driver. After the driver sends a request to the TPM, it keeps polling the device with I2C read request. The real AT97SC3204T hardware ignore those requests while the response is not ready simply by not ACKing the I2C read on its address. When the response is ready it will ACK the request and proceed writing the response in the wire. The QEMU I2C API does not provide a way to not ACK I2C requests when the device is not ready to transmit. In fact, if the device has been configured in the virtual machine, QEMU will automatically ACK every request without asking for the device permission for it. Therefore we created a flag in the I2CSlave struct that tells the I2C subsystem that the device is busy and not ready to ACK a I2C transfer. We understand that it could not be the best solution to the problem, but it appears to be the solution that have the least impact in the code overall. Suggestions on a different approach would be welcome. ### Testing ### We tested the feature in the versatilepb machine running Linux with TrouSerS and tpm_tools: qemu-system-arm -M versatilepb -kernel output/images/zImage \ -dtb output/images/versatile-pb.dtb \ -drive file=output/images/rootfs.ext2,if=scsi,format=raw \ -append "root=/dev/sda console=ttyAMA0,115200" -net nic,model=rtl8139 \ -net user -nographic -device tpm-tis,tpmdev=tpm-tpm0,address=0x20 \ -tpmdev passthrough,id=tpm-tpm0,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:08/tpm/tpm0/cancel The following device needed to be included on the Device Tree: i2c0: i2c@10002000 { #address-cells = <1>; #size-cells = <0>; compatible = "arm,versatile-i2c"; reg = <0x10002000 0x1000>; rtc@68 { compatible = "dallas,ds1338"; reg = <0x68>; }; tpm@20 { compatible = "atmel,at97sc3204t"; reg = <0x20>; }; The following config needed to be enabled in the Linux Kernel: I2C_VERSATILE=y TCG_TPM=y TCG_TIS_I2C_ATMEL=y ### Changes from V0 to v1 ### - Fixed coding style problems found by Patchew. Fabio Urquiza (2): i2c: Add flag to NACK I2C transfers when busy tpm: Add TPM I2C Atmel frontend default-configs/aarch64-softmmu.mak | 1 + default-configs/arm-softmmu.mak | 1 + hw/i2c/core.c | 3 + hw/tpm/Makefile.objs | 1 + hw/tpm/tpm_i2c_atmel.c | 362 ++++++++++++++++++++++++++++++++++++ include/hw/i2c/i2c.h | 1 + 6 files changed, 369 insertions(+) create mode 100644 hw/tpm/tpm_i2c_atmel.c -- 2.8.3