系列文章目录
第一章 QEMU系统仿真 TPM 设备实例
第二章 QEMU系统 TPM-TIS 设备源码分析
第三章 QEMU系统 TPM-emulator 设备源码分析(上)
第四章 QEMU系统添加 Windows 主机软件 TPM 设备支持
文章目录
前言
本文以 QEMU 8.2.2 为例,分析其 TPM-emulator 模块的实现,并为 QEMU 添加 Windows 平台的TPM 模拟器的支持。
本文读者需要具备一定的 QEMU 使用经验,并对 C 语言编程有一定了解。
在 QEMU 启动时需要提供如下参数完成 TPM-emulator 的设置:
-chardev "socket,id=chrtpm,path=swtpm-sock"
-tpmdev "emulator,id=tpm0,chardev=chrtpm"
-device "tpm-tis,tpmdev=tpm0"
本文将分析 TPM-emulator 模块实现部分中与 swtpm 软件 TPM 程序建立控制通道(ctrlchannel)的部分代码,这部分代码是 TPM-emulator 创建时需首先完成的工作。
一、TPM-emulator是什么?
QEMU 支持对 TPM 设备的仿真,在没有硬件支持的环境中,我们可以使用 swtpm 来替代 TPM 硬件设备,为系统提供 TPM 支持。
在 QEMU 启动时需要提供如下参数完成 TPM-emulator 的设置:
-chardev "socket,id=chrtpm,path=swtpm-sock"
-tpmdev "emulator,id=tpm0,chardev=chrtpm"
-device "tpm-tis,tpmdev=tpm0"
二、QEMU 中 TPM-emulator 的实现
1.代码分析
TPM-emulator 的代码位于 backend/tpm/tpm_emulator.c 中
首先,设备申明代码如下:
type_init(tpm_emulator_register)
函数 tpm_emulator_register() 为设备的注册函数,代码如下:
static void tpm_emulator_register(void)
{
type_register_static(&tpm_emulator_info);
}
结构体 tpm_emulator_info 定义为:
static const TypeInfo tpm_emulator_info = {
.name = TYPE_TPM_EMULATOR,
.parent = TYPE_TPM_BACKEND,
.instance_size = sizeof(TPMEmulator),
.class_init = tpm_emulator_class_init,
.instance_init = tpm_emulator_inst_init,
.instance_finalize = tpm_emulator_inst_finalize,
};
根据设备在系统中注册的过程,首先需要注册设备类,然后完成设备实例的初始化,因此我们首先进入设备类初始化函数 tpm_emulator_class_init()
.class_init = tpm_emulator_class_init,
};
函数 tpm_emulator_class_init()代码如下:
static void tpm_emulator_class_init(ObjectClass *klass, void *data)
{
TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
tbc->type = TPM_TYPE_EMULATOR;
tbc->opts = tpm_emulator_cmdline_opts;
tbc->desc = "TPM emulator backend driver";
tbc->create = tpm_emulator_create;
tbc->startup_tpm = tpm_emulator_startup_tpm;
tbc->cancel_cmd = tpm_emulator_cancel_cmd;
tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag;
tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag;
tbc->get_tpm_version = tpm_emulator_get_tpm_version;
tbc->get_buffer_size = tpm_emulator_get_buffer_size;
tbc->get_tpm_options = tpm_emulator_get_tpm_options;
tbc->handle_request = tpm_emulator_handle_request;
}
系统运行首先需要创建设备类,因此我们查看 tpm_emulator_create() 函数
static TPMBackend *tpm_emulator_create(QemuOpts *opts)
{
TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
object_unref(OBJECT(tb));
return NULL;
}
return tb;
}
tpm_emulator_create() 函数首先通过 tpm_emulator_handle_device_opts() 注册该设备类的各个操作函数
static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
{
const char *value;
Error *err = NULL;
Chardev *dev;
value = qemu_opt_get(opts, "chardev");
if (!value) {
error_report("tpm-emulator: parameter 'chardev' is missing");
goto err;
}
dev = qemu_chr_find(value);
if (!dev) {
error_report("tpm-emulator: tpm chardev '%s' not found", value);
goto err;
}
if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
value);
error_report_err(err);
goto err;
}
tpm_emu->options->chardev = g_strdup(value);
if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
goto err;
}
/* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
* by passthrough driver, which not yet using GIOChannel.
*/
if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd,
&tpm_emu->tpm_version)) {
error_report("'%s' is not emulating TPM device. Error: %s",
tpm_emu->options->chardev, strerror(errno));
goto err;
}
switch (tpm_emu->tpm_version) {
case TPM_VERSION_1_2:
trace_tpm_emulator_handle_device_opts_tpm12();
break;
case TPM_VERSION_2_0:
trace_tpm_emulator_handle_device_opts_tpm2();
break;
default:
trace_tpm_emulator_handle_device_opts_unspec();
}
if (tpm_emulator_probe_caps

本文以QEMU 8.2.2为例,分析其TPM-emulator模块实现,并为QEMU添加Windows平台TPM模拟器支持。介绍了TPM-emulator概念,详细分析其代码,包括与swtpm建立数据通道的过程。指出因Windows系统不支持相关功能,可利用其UNIX本地套接字支持建立数据通道。
】&spm=1001.2101.3001.5002&articleId=137710531&d=1&t=3&u=87d13cbb106f4871bd27941b1b175d85)
2210

被折叠的 条评论
为什么被折叠?



