1
From: James Bottomley <James.Bottomley@HansenPartnership.com>
2
3
The requested feedback was to convert the tpmdev handler to being json
1
The requested feedback was to convert the tpmdev handler to being json
4
based, which requires rethreading all the backends. The good news is
2
based, which requires rethreading all the backends. The good news is
5
this reduced quite a bit of code (especially as I converted it to
3
this reduced quite a bit of code (especially as I converted it to
6
error_fatal handling as well, which removes the return status
4
error_fatal handling as well, which removes the return status
7
threading). The bad news is I can't test any of the conversions.
5
threading).
8
swtpm still isn't building on opensuse and, apparently, passthrough
9
doesn't like my native TPM because it doesn't allow cancellation.
10
6
11
v3 pulls out more unneeded code in the visitor conversion, makes
7
v3 pulls out more unneeded code in the visitor conversion, makes
12
migration work on external state preservation of the simulator and
8
migration work on external state preservation of the simulator and
13
adds documentation
9
adds documentation
14
10
15
v4 puts back the wrapper options (but doesn't add any for mssim since
11
v4 puts back the wrapper options (but doesn't add any for mssim since
16
it post dates the necessity)
12
it post dates the necessity)
13
14
v5 rebases to the latest master branch and adjusts for removed use_FOO ptrs
15
16
v5 updates help to exit zero; does some checkpatch tidying
17
18
v7 merge review feedback and add acks.
19
20
v8 adds better error handling, more code tidies and adds command
21
socket disconnection/reconnection (instead of trying to keep the
22
socket open the whole time). This adds overhead, but makes
23
debugging guest kernel TPM issues much easier.
24
25
v9 Fix merge conflict with optarg->optstr conversion
26
27
v10 Fix more merge conflicts and update API versions
28
29
v11 Fix another merge conflict and correct a warm reboot problem where
30
the TPM isn't getting reset (meaning the PCR values are wrong).
17
31
18
James
32
James
19
33
20
---
34
---
21
35
...
...
24
tpm: add backend for mssim
38
tpm: add backend for mssim
25
39
26
MAINTAINERS | 6 +
40
MAINTAINERS | 6 +
27
backends/tpm/Kconfig | 5 +
41
backends/tpm/Kconfig | 5 +
28
backends/tpm/meson.build | 1 +
42
backends/tpm/meson.build | 1 +
29
backends/tpm/tpm_emulator.c | 24 ++-
43
backends/tpm/tpm_emulator.c | 25 +--
30
backends/tpm/tpm_mssim.c | 265 +++++++++++++++++++++++++++++++++
44
backends/tpm/tpm_mssim.c | 335 +++++++++++++++++++++++++++++++++
31
backends/tpm/tpm_mssim.h | 43 ++++++
45
backends/tpm/tpm_mssim.h | 44 +++++
32
backends/tpm/tpm_passthrough.c | 27 +---
46
backends/tpm/tpm_passthrough.c | 23 +--
33
docs/specs/tpm.rst | 35 +++++
47
docs/specs/tpm.rst | 39 ++++
34
include/sysemu/tpm.h | 4 +-
48
include/sysemu/tpm.h | 5 +-
35
include/sysemu/tpm_backend.h | 2 +-
49
include/sysemu/tpm_backend.h | 2 +-
36
monitor/hmp-cmds.c | 7 +
50
qapi/tpm.json | 50 ++++-
37
qapi/tpm.json | 45 +++++-
51
system/tpm-hmp-cmds.c | 9 +
38
softmmu/tpm.c | 90 +++++------
52
system/tpm.c | 91 ++++-----
39
softmmu/vl.c | 19 +--
53
system/vl.c | 19 +-
40
14 files changed, 461 insertions(+), 112 deletions(-)
54
14 files changed, 546 insertions(+), 108 deletions(-)
41
create mode 100644 backends/tpm/tpm_mssim.c
55
create mode 100644 backends/tpm/tpm_mssim.c
42
create mode 100644 backends/tpm/tpm_mssim.h
56
create mode 100644 backends/tpm/tpm_mssim.h
43
57
44
--
58
--
45
2.35.3
59
2.35.3
diff view generated by jsdifflib
1
From: James Bottomley <James.Bottomley@HansenPartnership.com>
2
3
Instead of processing the tpmdev options using the old qemu options,
1
Instead of processing the tpmdev options using the old qemu options,
4
convert to the new visitor format which also allows the passing of
2
convert to the new visitor format which also allows the passing of
5
json on the command line.
3
json on the command line.
6
4
7
Signed-off-by: James Bottomley <jejb@linux.ibm.com>
5
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
6
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
7
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
8
8
9
---
9
---
10
v4: add TpmConfiOptions
10
v4: add TpmConfiOptions
11
v5: exit(0) for help
12
v7: adjust line lengths, free options
13
v8: minor updates; add tested/reviewed-by
14
v9: optarg->optstr
11
---
15
---
12
backends/tpm/tpm_emulator.c | 24 ++++-----
16
backends/tpm/tpm_emulator.c | 25 ++++------
13
backends/tpm/tpm_passthrough.c | 27 +++-------
17
backends/tpm/tpm_passthrough.c | 23 +++------
14
include/sysemu/tpm.h | 4 +-
18
include/sysemu/tpm.h | 5 +-
15
include/sysemu/tpm_backend.h | 2 +-
19
include/sysemu/tpm_backend.h | 2 +-
16
qapi/tpm.json | 19 +++++++
20
qapi/tpm.json | 21 ++++++++
17
softmmu/tpm.c | 90 ++++++++++++++--------------------
21
system/tpm.c | 91 ++++++++++++++--------------------
18
softmmu/vl.c | 19 +------
22
system/vl.c | 19 +------
19
7 files changed, 76 insertions(+), 109 deletions(-)
23
7 files changed, 81 insertions(+), 105 deletions(-)
20
24
21
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
25
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
22
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
23
--- a/backends/tpm/tpm_emulator.c
27
--- a/backends/tpm/tpm_emulator.c
24
+++ b/backends/tpm/tpm_emulator.c
28
+++ b/backends/tpm/tpm_emulator.c
25
@@ -XXX,XX +XXX,XX @@ err_exit:
29
@@ -XXX,XX +XXX,XX @@ err_exit:
26
return -1;
30
return -1;
27
}
31
}
28
32
29
-static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
33
-static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
30
+static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, TpmCreateOptions *opts)
34
+static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu,
35
+ TpmCreateOptions *opts)
31
{
36
{
32
- const char *value;
37
- const char *value;
33
Error *err = NULL;
38
Error *err = NULL;
34
Chardev *dev;
39
Chardev *dev;
35
40
...
...
44
- dev = qemu_chr_find(value);
49
- dev = qemu_chr_find(value);
45
+ dev = qemu_chr_find(opts->u.emulator.chardev);
50
+ dev = qemu_chr_find(opts->u.emulator.chardev);
46
if (!dev) {
51
if (!dev) {
47
- error_report("tpm-emulator: tpm chardev '%s' not found", value);
52
- error_report("tpm-emulator: tpm chardev '%s' not found", value);
48
+ error_report("tpm-emulator: tpm chardev '%s' not found",
53
+ error_report("tpm-emulator: tpm chardev '%s' not found",
49
+ opts->u.emulator.chardev);
54
+ opts->u.emulator.chardev);
50
goto err;
55
goto err;
51
}
56
}
52
57
53
if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
58
if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
54
error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
59
error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
...
...
96
@@ -XXX,XX +XXX,XX @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
101
@@ -XXX,XX +XXX,XX @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
97
}
102
}
98
103
99
static int
104
static int
100
-tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
105
-tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
101
+tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, TpmCreateOptions *opts)
106
+tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt,
107
+ TpmCreateOptions *opts)
102
{
108
{
103
- const char *value;
109
- const char *value;
104
+ tpm_pt->options = QAPI_CLONE(TPMPassthroughOptions, &opts->u.passthrough);
110
+ tpm_pt->options = QAPI_CLONE(TPMPassthroughOptions, &opts->u.passthrough);
105
111
106
- value = qemu_opt_get(opts, "cancel-path");
112
- value = qemu_opt_get(opts, "cancel-path");
107
- if (value) {
113
- if (value) {
108
- tpm_pt->options->cancel_path = g_strdup(value);
114
- tpm_pt->options->cancel_path = g_strdup(value);
109
- tpm_pt->options->has_cancel_path = true;
110
- }
115
- }
111
-
116
-
112
- value = qemu_opt_get(opts, "path");
117
- value = qemu_opt_get(opts, "path");
113
- if (value) {
118
- if (value) {
114
- tpm_pt->options->has_path = true;
115
- tpm_pt->options->path = g_strdup(value);
119
- tpm_pt->options->path = g_strdup(value);
116
- }
120
- }
117
-
121
-
118
- tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE;
122
- tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE;
119
+ tpm_pt->tpm_dev = opts->u.passthrough.has_path ? opts->u.passthrough.path : TPM_PASSTHROUGH_DEFAULT_DEVICE;
123
+ tpm_pt->tpm_dev = opts->u.passthrough.path ? opts->u.passthrough.path :
124
+ TPM_PASSTHROUGH_DEFAULT_DEVICE;
120
tpm_pt->tpm_fd = qemu_open_old(tpm_pt->tpm_dev, O_RDWR);
125
tpm_pt->tpm_fd = qemu_open_old(tpm_pt->tpm_dev, O_RDWR);
121
if (tpm_pt->tpm_fd < 0) {
126
if (tpm_pt->tpm_fd < 0) {
122
error_report("Cannot access TPM device using '%s': %s",
127
error_report("Cannot access TPM device using '%s': %s",
123
@@ -XXX,XX +XXX,XX @@ tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
128
@@ -XXX,XX +XXX,XX @@ tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
124
return 0;
129
return 0;
...
...
132
- if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), opts)) {
137
- if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), opts)) {
133
+ if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), tco)) {
138
+ if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), tco)) {
134
object_unref(obj);
139
object_unref(obj);
135
return NULL;
140
return NULL;
136
}
141
}
137
@@ -XXX,XX +XXX,XX @@ static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
138
TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
139
140
options->type = TPM_TYPE_PASSTHROUGH;
141
- options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
142
- TPM_PASSTHROUGH(tb)->options);
143
+
144
+ options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions, TPM_PASSTHROUGH(tb)->options);
145
146
return options;
147
}
148
@@ -XXX,XX +XXX,XX @@ static void tpm_passthrough_inst_init(Object *obj)
142
@@ -XXX,XX +XXX,XX @@ static void tpm_passthrough_inst_init(Object *obj)
149
{
143
{
150
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
144
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
151
145
152
- tpm_pt->options = g_new0(TPMPassthroughOptions, 1);
146
- tpm_pt->options = g_new0(TPMPassthroughOptions, 1);
...
...
159
+++ b/include/sysemu/tpm.h
153
+++ b/include/sysemu/tpm.h
160
@@ -XXX,XX +XXX,XX @@
154
@@ -XXX,XX +XXX,XX @@
161
155
162
#ifdef CONFIG_TPM
156
#ifdef CONFIG_TPM
163
157
164
-int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
158
-int tpm_config_parse(QemuOptsList *opts_list, const char *optstr);
165
-int tpm_init(void);
159
-int tpm_init(void);
166
+void tpm_config_parse(const char *optarg);
160
+void tpm_config_parse(const char *optstr);
167
+void tpm_init(void);
161
+void tpm_init(void);
162
+
168
void tpm_cleanup(void);
163
void tpm_cleanup(void);
169
164
170
typedef enum TPMVersion {
165
typedef enum TPMVersion {
171
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
166
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
172
index XXXXXXX..XXXXXXX 100644
167
index XXXXXXX..XXXXXXX 100644
...
...
196
+# without the wrapper to be usable by visitors.
191
+# without the wrapper to be usable by visitors.
197
+#
192
+#
198
+# @type: - 'passthrough' The configuration options for the TPM passthrough type
193
+# @type: - 'passthrough' The configuration options for the TPM passthrough type
199
+# - 'emulator' The configuration options for TPM emulator backend type
194
+# - 'emulator' The configuration options for TPM emulator backend type
200
+#
195
+#
201
+# Since: 7.2
196
+# @id: The Id of the TPM
197
+#
198
+# Since: 9.0
202
+##
199
+##
203
+{ 'union': 'TpmCreateOptions',
200
+{ 'union': 'TpmCreateOptions',
204
+ 'base': { 'type': 'TpmType',
201
+ 'base': { 'type': 'TpmType',
205
+ 'id' : 'str' },
202
+ 'id' : 'str' },
206
+ 'discriminator': 'type',
203
+ 'discriminator': 'type',
...
...
209
+ 'if': 'CONFIG_TPM' }
206
+ 'if': 'CONFIG_TPM' }
210
+
207
+
211
##
208
##
212
# @TPMInfo:
209
# @TPMInfo:
213
#
210
#
214
diff --git a/softmmu/tpm.c b/softmmu/tpm.c
211
diff --git a/system/tpm.c b/system/tpm.c
215
index XXXXXXX..XXXXXXX 100644
212
index XXXXXXX..XXXXXXX 100644
216
--- a/softmmu/tpm.c
213
--- a/system/tpm.c
217
+++ b/softmmu/tpm.c
214
+++ b/system/tpm.c
218
@@ -XXX,XX +XXX,XX @@
215
@@ -XXX,XX +XXX,XX @@
219
#include "qapi/error.h"
216
#include "qapi/error.h"
220
#include "qapi/qapi-commands-tpm.h"
217
#include "qapi/qapi-commands-tpm.h"
221
#include "qapi/qmp/qerror.h"
218
#include "qapi/qmp/qerror.h"
222
+#include "qapi/qobject-input-visitor.h"
219
+#include "qapi/qobject-input-visitor.h"
...
...
328
+ TpmCreateOptionsQueueEntry *tcoqe = QSIMPLEQ_FIRST(&tco_queue);
325
+ TpmCreateOptionsQueueEntry *tcoqe = QSIMPLEQ_FIRST(&tco_queue);
329
326
330
- return 0;
327
- return 0;
331
+ QSIMPLEQ_REMOVE_HEAD(&tco_queue, entry);
328
+ QSIMPLEQ_REMOVE_HEAD(&tco_queue, entry);
332
+ tpm_init_tpmdev(tcoqe->tco);
329
+ tpm_init_tpmdev(tcoqe->tco);
330
+ qapi_free_TpmCreateOptions(tcoqe->tco);
333
+ g_free(tcoqe);
331
+ g_free(tcoqe);
334
+ }
332
+ }
335
}
333
}
336
334
337
/*
335
/*
338
* Parse the TPM configuration options.
336
* Parse the TPM configuration options.
339
* To display all available TPM backends the user may use '-tpmdev help'
337
* To display all available TPM backends the user may use '-tpmdev help'
340
*/
338
*/
341
-int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
339
-int tpm_config_parse(QemuOptsList *opts_list, const char *optstr)
342
+void tpm_config_parse(const char *optarg)
340
+void tpm_config_parse(const char *optstr)
343
{
341
{
344
- QemuOpts *opts;
342
- QemuOpts *opts;
345
+ Visitor *v;
343
+ Visitor *v;
346
+ TpmCreateOptionsQueueEntry *tcqe;
344
+ TpmCreateOptionsQueueEntry *tcqe;
347
345
348
- if (!strcmp(optarg, "help")) {
346
- if (!strcmp(optstr, "help")) {
349
+ if (is_help_option(optarg)) {
347
+ if (is_help_option(optstr)) {
350
tpm_display_backend_drivers();
348
tpm_display_backend_drivers();
351
- return -1;
349
- return -1;
352
- }
350
- }
353
- opts = qemu_opts_parse_noisily(opts_list, optarg, true);
351
- opts = qemu_opts_parse_noisily(opts_list, optstr, true);
354
- if (!opts) {
352
- if (!opts) {
355
- return -1;
353
- return -1;
356
+ return;
354
+ exit(0);
357
}
355
}
358
- return 0;
356
- return 0;
359
+ v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
357
+ v = qobject_input_visitor_new_str(optstr, "type", &error_fatal);
360
+ tcqe = g_new(TpmCreateOptionsQueueEntry, 1);
358
+ tcqe = g_new(TpmCreateOptionsQueueEntry, 1);
361
+ visit_type_TpmCreateOptions(v, NULL, &tcqe->tco, &error_fatal);
359
+ visit_type_TpmCreateOptions(v, NULL, &tcqe->tco, &error_fatal);
362
+ visit_free(v);
360
+ visit_free(v);
363
+ QSIMPLEQ_INSERT_TAIL(&tco_queue, tcqe, entry);
361
+ QSIMPLEQ_INSERT_TAIL(&tco_queue, tcqe, entry);
364
}
362
}
365
363
366
/*
364
/*
367
diff --git a/softmmu/vl.c b/softmmu/vl.c
365
diff --git a/system/vl.c b/system/vl.c
368
index XXXXXXX..XXXXXXX 100644
366
index XXXXXXX..XXXXXXX 100644
369
--- a/softmmu/vl.c
367
--- a/system/vl.c
370
+++ b/softmmu/vl.c
368
+++ b/system/vl.c
371
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_object_opts = {
369
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qemu_object_opts = {
372
},
370
},
373
};
371
};
374
372
375
-static QemuOptsList qemu_tpmdev_opts = {
373
-static QemuOptsList qemu_tpmdev_opts = {
...
...
384
-
382
-
385
static QemuOptsList qemu_overcommit_opts = {
383
static QemuOptsList qemu_overcommit_opts = {
386
.name = "overcommit",
384
.name = "overcommit",
387
.head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head),
385
.head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head),
388
@@ -XXX,XX +XXX,XX @@ static void qemu_create_late_backends(void)
386
@@ -XXX,XX +XXX,XX @@ static void qemu_create_late_backends(void)
389
387
exit(1);
390
object_option_foreach_add(object_create_late);
388
}
391
389
392
- if (tpm_init() < 0) {
390
- if (tpm_init() < 0) {
393
- exit(1);
391
- exit(1);
394
- }
392
- }
395
+ tpm_init();
393
+ tpm_init();
...
...
diff view generated by jsdifflib
1
From: James Bottomley <James.Bottomley@HansenPartnership.com>
2
3
The Microsoft Simulator (mssim) is the reference emulation platform
1
The Microsoft Simulator (mssim) is the reference emulation platform
4
for the TCG TPM 2.0 specification.
2
for the TCG TPM 2.0 specification.
5
3
6
https://github.com/Microsoft/ms-tpm-20-ref.git
4
https://github.com/Microsoft/ms-tpm-20-ref.git
7
5
...
...
34
32
35
-tpmdev "{'type':'mssim','id':'tpm0','command':{'type':inet,'host':'remote','port':'2321'}}"
33
-tpmdev "{'type':'mssim','id':'tpm0','command':{'type':inet,'host':'remote','port':'2321'}}"
36
34
37
tpm-tis also works as the backend.
35
tpm-tis also works as the backend.
38
36
39
Signed-off-by: James Bottomley <jejb@linux.ibm.com>
37
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
38
Acked-by: Markus Armbruster <armbru@redhat.com>
40
39
41
---
40
---
42
41
43
v2: convert to SocketAddr json and use qio_channel_socket_connect_sync()
42
v2: convert to SocketAddr json and use qio_channel_socket_connect_sync()
44
v3: gate control power off by migration state keep control socket disconnected
43
v3: gate control power off by migration state keep control socket disconnected
45
to test outside influence and add docs.
44
to test outside influence and add docs.
45
v7: TPMmssim -> TPMMssim; doc and json fixes
46
Make command socket open each time (makes OS debugging easier)
47
v11: add startup method to make sure TPM is reset on reboot
46
---
48
---
47
MAINTAINERS | 6 +
49
MAINTAINERS | 6 +
48
backends/tpm/Kconfig | 5 +
50
backends/tpm/Kconfig | 5 +
49
backends/tpm/meson.build | 1 +
51
backends/tpm/meson.build | 1 +
50
backends/tpm/tpm_mssim.c | 265 +++++++++++++++++++++++++++++++++++++++
52
backends/tpm/tpm_mssim.c | 335 +++++++++++++++++++++++++++++++++++++++
51
backends/tpm/tpm_mssim.h | 43 +++++++
53
backends/tpm/tpm_mssim.h | 44 +++++
52
docs/specs/tpm.rst | 35 ++++++
54
docs/specs/tpm.rst | 39 +++++
53
monitor/hmp-cmds.c | 7 ++
55
qapi/tpm.json | 31 +++-
54
qapi/tpm.json | 28 ++++-
56
system/tpm-hmp-cmds.c | 9 ++
55
8 files changed, 386 insertions(+), 4 deletions(-)
57
8 files changed, 466 insertions(+), 4 deletions(-)
56
create mode 100644 backends/tpm/tpm_mssim.c
58
create mode 100644 backends/tpm/tpm_mssim.c
57
create mode 100644 backends/tpm/tpm_mssim.h
59
create mode 100644 backends/tpm/tpm_mssim.h
58
60
59
diff --git a/MAINTAINERS b/MAINTAINERS
61
diff --git a/MAINTAINERS b/MAINTAINERS
60
index XXXXXXX..XXXXXXX 100644
62
index XXXXXXX..XXXXXXX 100644
...
...
64
F: include/sysemu/tpm*
66
F: include/sysemu/tpm*
65
F: qapi/tpm.json
67
F: qapi/tpm.json
66
F: backends/tpm/
68
F: backends/tpm/
67
+X: backends/tpm/tpm_mssim.*
69
+X: backends/tpm/tpm_mssim.*
68
F: tests/qtest/*tpm*
70
F: tests/qtest/*tpm*
71
F: docs/specs/tpm.rst
69
T: git https://github.com/stefanberger/qemu-tpm.git tpm-next
72
T: git https://github.com/stefanberger/qemu-tpm.git tpm-next
70
73
71
+MSSIM TPM Backend
74
+MSSIM TPM Backend
72
+M: James Bottomley <jejb@linux.ibm.com>
75
+M: James Bottomley <jejb@linux.ibm.com>
73
+S: Maintained
76
+S: Maintained
74
+F: backends/tpm/tpm_mssim.*
77
+F: backends/tpm/tpm_mssim.*
75
+
78
+
76
Checkpatch
79
SPDM
77
S: Odd Fixes
80
M: Alistair Francis <alistair.francis@wdc.com>
78
F: scripts/checkpatch.pl
81
S: Maintained
79
diff --git a/backends/tpm/Kconfig b/backends/tpm/Kconfig
82
diff --git a/backends/tpm/Kconfig b/backends/tpm/Kconfig
80
index XXXXXXX..XXXXXXX 100644
83
index XXXXXXX..XXXXXXX 100644
81
--- a/backends/tpm/Kconfig
84
--- a/backends/tpm/Kconfig
82
+++ b/backends/tpm/Kconfig
85
+++ b/backends/tpm/Kconfig
83
@@ -XXX,XX +XXX,XX @@ config TPM_EMULATOR
86
@@ -XXX,XX +XXX,XX @@ config TPM_EMULATOR
...
...
92
diff --git a/backends/tpm/meson.build b/backends/tpm/meson.build
95
diff --git a/backends/tpm/meson.build b/backends/tpm/meson.build
93
index XXXXXXX..XXXXXXX 100644
96
index XXXXXXX..XXXXXXX 100644
94
--- a/backends/tpm/meson.build
97
--- a/backends/tpm/meson.build
95
+++ b/backends/tpm/meson.build
98
+++ b/backends/tpm/meson.build
96
@@ -XXX,XX +XXX,XX @@ if have_tpm
99
@@ -XXX,XX +XXX,XX @@ if have_tpm
97
softmmu_ss.add(files('tpm_util.c'))
100
system_ss.add(files('tpm_util.c'))
98
softmmu_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c'))
101
system_ss.add(when: 'CONFIG_TPM_PASSTHROUGH', if_true: files('tpm_passthrough.c'))
99
softmmu_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c'))
102
system_ss.add(when: 'CONFIG_TPM_EMULATOR', if_true: files('tpm_emulator.c'))
100
+ softmmu_ss.add(when: 'CONFIG_TPM_MSSIM', if_true: files('tpm_mssim.c'))
103
+ system_ss.add(when: 'CONFIG_TPM_MSSIM', if_true: files('tpm_mssim.c'))
101
endif
104
endif
102
diff --git a/backends/tpm/tpm_mssim.c b/backends/tpm/tpm_mssim.c
105
diff --git a/backends/tpm/tpm_mssim.c b/backends/tpm/tpm_mssim.c
103
new file mode 100644
106
new file mode 100644
104
index XXXXXXX..XXXXXXX
107
index XXXXXXX..XXXXXXX
105
--- /dev/null
108
--- /dev/null
...
...
132
+#include "tpm_mssim.h"
135
+#include "tpm_mssim.h"
133
+
136
+
134
+#define ERROR_PREFIX "TPM mssim Emulator: "
137
+#define ERROR_PREFIX "TPM mssim Emulator: "
135
+
138
+
136
+#define TYPE_TPM_MSSIM "tpm-mssim"
139
+#define TYPE_TPM_MSSIM "tpm-mssim"
137
+OBJECT_DECLARE_SIMPLE_TYPE(TPMmssim, TPM_MSSIM)
140
+OBJECT_DECLARE_SIMPLE_TYPE(TPMMssim, TPM_MSSIM)
138
+
141
+
139
+struct TPMmssim {
142
+struct TPMMssim {
140
+ TPMBackend parent;
143
+ TPMBackend parent;
141
+
144
+
142
+ TPMmssimOptions opts;
145
+ TPMMssimOptions opts;
143
+
146
+
144
+ QIOChannelSocket *cmd_qc, *ctrl_qc;
147
+ QIOChannelSocket *cmd_qc, *ctrl_qc;
145
+};
148
+};
146
+
149
+
147
+static int tpm_send_ctrl(TPMmssim *t, uint32_t cmd, Error **errp)
150
+static int tpm_send_ctrl(TPMMssim *t, uint32_t cmd, Error **errp)
148
+{
151
+{
149
+ int ret;
152
+ int ret, retc;
150
+
153
+ Error *local_err = NULL;
151
+ qio_channel_socket_connect_sync(t->ctrl_qc, t->opts.control, errp);
154
+
155
+ ret = qio_channel_socket_connect_sync(t->ctrl_qc, t->opts.control, errp);
156
+ if (ret != 0) {
157
+ return ret;
158
+ }
152
+ cmd = htonl(cmd);
159
+ cmd = htonl(cmd);
153
+ ret = qio_channel_write_all(QIO_CHANNEL(t->ctrl_qc), (char *)&cmd, sizeof(cmd), errp);
160
+ ret = qio_channel_write_all(QIO_CHANNEL(t->ctrl_qc),
154
+ if (ret != 0)
161
+ (char *)&cmd, sizeof(cmd), errp);
162
+ if (ret != 0) {
155
+ goto out;
163
+ goto out;
156
+ ret = qio_channel_read_all(QIO_CHANNEL(t->ctrl_qc), (char *)&cmd, sizeof(cmd), errp);
164
+ }
157
+ if (ret != 0)
165
+
166
+ ret = qio_channel_read_all(QIO_CHANNEL(t->ctrl_qc),
167
+ (char *)&cmd, sizeof(cmd), errp);
168
+ if (ret != 0) {
158
+ goto out;
169
+ goto out;
170
+ }
159
+ if (cmd != 0) {
171
+ if (cmd != 0) {
160
+ error_setg(errp, ERROR_PREFIX "Incorrect ACK recieved on control channel 0x%x\n", cmd);
172
+ error_setg(errp, ERROR_PREFIX
173
+ "Incorrect ACK recieved on control channel 0x%x", cmd);
161
+ ret = -1;
174
+ ret = -1;
162
+ }
175
+ }
163
+ out:
176
+ out:
164
+ qio_channel_close(QIO_CHANNEL(t->ctrl_qc), errp);
177
+ /*
165
+ return ret;
178
+ * need to close the channel here, but if that fails report it
179
+ * while not letting a prior failure get overwritten
180
+ */
181
+ retc = qio_channel_close(QIO_CHANNEL(t->ctrl_qc), &local_err);
182
+ error_propagate(errp, local_err);
183
+ return retc ? retc : ret;
166
+}
184
+}
167
+
185
+
168
+static void tpm_mssim_instance_init(Object *obj)
186
+static void tpm_mssim_instance_init(Object *obj)
169
+{
187
+{
170
+}
188
+}
171
+
189
+
172
+static void tpm_mssim_instance_finalize(Object *obj)
190
+static void tpm_mssim_instance_finalize(Object *obj)
173
+{
191
+{
174
+ TPMmssim *t = TPM_MSSIM(obj);
192
+ TPMMssim *t = TPM_MSSIM(obj);
175
+
193
+
176
+ if (t->ctrl_qc && !runstate_check(RUN_STATE_INMIGRATE))
194
+ if (t->cmd_qc && !runstate_check(RUN_STATE_POSTMIGRATE)) {
177
+ tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, NULL);
195
+ Error *errp = NULL;
196
+ int ret;
197
+
198
+ ret = tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, &errp);
199
+ if (ret != 0) {
200
+ error_report_err(errp);
201
+ }
202
+ }
178
+
203
+
179
+ object_unref(OBJECT(t->ctrl_qc));
204
+ object_unref(OBJECT(t->ctrl_qc));
180
+ object_unref(OBJECT(t->cmd_qc));
205
+ object_unref(OBJECT(t->cmd_qc));
181
+}
206
+}
182
+
207
+
...
...
196
+ return 4096;
221
+ return 4096;
197
+}
222
+}
198
+
223
+
199
+static TpmTypeOptions *tpm_mssim_get_opts(TPMBackend *tb)
224
+static TpmTypeOptions *tpm_mssim_get_opts(TPMBackend *tb)
200
+{
225
+{
201
+ TPMmssim *t = TPM_MSSIM(tb);
226
+ TPMMssim *t = TPM_MSSIM(tb);
202
+ TpmTypeOptions *opts = g_new0(TpmTypeOptions, 1);
227
+ TpmTypeOptions *opts = g_new0(TpmTypeOptions, 1);
203
+
228
+
204
+ opts->type = TPM_TYPE_MSSIM;
229
+ opts->type = TPM_TYPE_MSSIM;
205
+ opts->u.mssim = t->opts;
230
+ QAPI_CLONE_MEMBERS(TPMMssimOptions, &opts->u.mssim, &t->opts);
206
+
231
+
207
+ return opts;
232
+ return opts;
208
+}
233
+}
209
+
234
+
210
+static void tpm_mssim_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
235
+static void tpm_mssim_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
211
+ Error **errp)
236
+ Error **errp)
212
+{
237
+{
213
+ TPMmssim *t = TPM_MSSIM(tb);
238
+ TPMMssim *t = TPM_MSSIM(tb);
214
+ uint32_t header, len;
239
+ uint32_t header, len;
215
+ uint8_t locality = cmd->locty;
240
+ uint8_t locality = cmd->locty;
216
+ struct iovec iov[4];
241
+ struct iovec iov[4];
217
+ int ret;
242
+ int ret;
243
+
244
+ ret = qio_channel_socket_connect_sync(t->cmd_qc, t->opts.command, errp);
245
+ if (ret != 0) {
246
+ goto fail_msg;
247
+ }
218
+
248
+
219
+ header = htonl(TPM_SEND_COMMAND);
249
+ header = htonl(TPM_SEND_COMMAND);
220
+ len = htonl(cmd->in_len);
250
+ len = htonl(cmd->in_len);
221
+
251
+
222
+ iov[0].iov_base = &header;
252
+ iov[0].iov_base = &header;
...
...
227
+ iov[2].iov_len = sizeof(len);
257
+ iov[2].iov_len = sizeof(len);
228
+ iov[3].iov_base = (void *)cmd->in;
258
+ iov[3].iov_base = (void *)cmd->in;
229
+ iov[3].iov_len = cmd->in_len;
259
+ iov[3].iov_len = cmd->in_len;
230
+
260
+
231
+ ret = qio_channel_writev_all(QIO_CHANNEL(t->cmd_qc), iov, 4, errp);
261
+ ret = qio_channel_writev_all(QIO_CHANNEL(t->cmd_qc), iov, 4, errp);
232
+ if (ret != 0)
262
+ if (ret != 0) {
233
+ goto fail;
263
+ goto fail;
234
+
264
+ }
235
+ ret = qio_channel_read_all(QIO_CHANNEL(t->cmd_qc), (char *)&len, sizeof(len), errp);
265
+
236
+ if (ret != 0)
266
+ ret = qio_channel_read_all(QIO_CHANNEL(t->cmd_qc),
237
+ goto fail;
267
+ (char *)&len, sizeof(len), errp);
268
+ if (ret != 0) {
269
+ goto fail;
270
+ }
271
+
238
+ len = ntohl(len);
272
+ len = ntohl(len);
239
+ if (len > cmd->out_len) {
273
+ if (len > cmd->out_len) {
240
+ error_setg(errp, "receive size is too large");
274
+ error_setg(errp, "receive size is too large");
241
+ goto fail;
275
+ goto fail;
242
+ }
276
+ }
243
+ ret = qio_channel_read_all(QIO_CHANNEL(t->cmd_qc), (char *)cmd->out, len, errp);
277
+ ret = qio_channel_read_all(QIO_CHANNEL(t->cmd_qc),
244
+ if (ret != 0)
278
+ (char *)cmd->out, len, errp);
245
+ goto fail;
279
+ if (ret != 0) {
280
+ goto fail;
281
+ }
282
+
246
+ /* ACK packet */
283
+ /* ACK packet */
247
+ ret = qio_channel_read_all(QIO_CHANNEL(t->cmd_qc), (char *)&header, sizeof(header), errp);
284
+ ret = qio_channel_read_all(QIO_CHANNEL(t->cmd_qc),
248
+ if (ret != 0)
285
+ (char *)&header, sizeof(header), errp);
249
+ goto fail;
286
+ if (ret != 0) {
287
+ goto fail;
288
+ }
250
+ if (header != 0) {
289
+ if (header != 0) {
251
+ error_setg(errp, "incorrect ACK received on command channel 0x%x", len);
290
+ error_setg(errp, "incorrect ACK received on command channel 0x%x", len);
252
+ goto fail;
291
+ goto fail;
253
+ }
292
+ }
254
+
293
+
294
+ ret = qio_channel_close(QIO_CHANNEL(t->cmd_qc), errp);
295
+ if (ret != 0) {
296
+ goto fail_msg;
297
+ }
298
+
255
+ return;
299
+ return;
256
+
300
+
257
+ fail:
301
+ fail:
302
+ /* we're already failing, so don't worry if this fails too */
303
+ qio_channel_close(QIO_CHANNEL(t->cmd_qc), NULL);
304
+ fail_msg:
258
+ error_prepend(errp, ERROR_PREFIX);
305
+ error_prepend(errp, ERROR_PREFIX);
259
+ tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
306
+ tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
260
+}
307
+}
261
+
308
+
309
+static int tpm_mssim_startup(TPMBackend *tb, size_t buffersize)
310
+{
311
+ TPMMssim *t = TPM_MSSIM(tb);
312
+ Error *errp = NULL;
313
+ int ret;
314
+
315
+ if (runstate_check(RUN_STATE_INMIGRATE)) {
316
+ return 0;
317
+ }
318
+
319
+ /*
320
+ * reset the TPM using a power cycle sequence, in case someone has
321
+ * previously powered it up
322
+ */
323
+ ret = tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, &errp);
324
+ if (ret != 0) {
325
+ goto fail;
326
+ }
327
+
328
+ ret = tpm_send_ctrl(t, TPM_SIGNAL_POWER_ON, &errp);
329
+ if (ret != 0) {
330
+ goto fail;
331
+ }
332
+
333
+ ret = tpm_send_ctrl(t, TPM_SIGNAL_NV_ON, &errp);
334
+ if (ret != 0) {
335
+ goto fail;
336
+ }
337
+
338
+ return 0;
339
+
340
+ fail:
341
+ error_report_err(errp);
342
+ return -1;
343
+}
344
+
262
+static TPMBackend *tpm_mssim_create(TpmCreateOptions *opts)
345
+static TPMBackend *tpm_mssim_create(TpmCreateOptions *opts)
263
+{
346
+{
264
+ TPMBackend *be = TPM_BACKEND(object_new(TYPE_TPM_MSSIM));
347
+ TPMBackend *be = TPM_BACKEND(object_new(TYPE_TPM_MSSIM));
265
+ TPMmssim *t = TPM_MSSIM(be);
348
+ TPMMssim *t = TPM_MSSIM(be);
266
+ int sock;
267
+ Error *errp = NULL;
349
+ Error *errp = NULL;
268
+ TPMmssimOptions *mo = &opts->u.mssim;
350
+ TPMMssimOptions *mo = &opts->u.mssim;
269
+
351
+
270
+ if (!mo->has_command) {
352
+ if (!mo->command) {
271
+ mo->has_command = true;
272
+ mo->command = g_new0(SocketAddress, 1);
353
+ mo->command = g_new0(SocketAddress, 1);
273
+ mo->command->type = SOCKET_ADDRESS_TYPE_INET;
354
+ mo->command->type = SOCKET_ADDRESS_TYPE_INET;
274
+ mo->command->u.inet.host = g_strdup("localhost");
355
+ mo->command->u.inet.host = g_strdup("localhost");
275
+ mo->command->u.inet.port = g_strdup("2321");
356
+ mo->command->u.inet.port = g_strdup("2321");
276
+ }
357
+ }
277
+ if (!mo->has_control) {
358
+ if (!mo->control) {
278
+ int port;
359
+ int port;
279
+
360
+
280
+ mo->has_control = true;
281
+ mo->control = g_new0(SocketAddress, 1);
361
+ mo->control = g_new0(SocketAddress, 1);
282
+ mo->control->type = SOCKET_ADDRESS_TYPE_INET;
362
+ mo->control->type = SOCKET_ADDRESS_TYPE_INET;
283
+ mo->control->u.inet.host = g_strdup(mo->command->u.inet.host);
363
+ mo->control->u.inet.host = g_strdup(mo->command->u.inet.host);
284
+ /* in the reference implementation, the control port is
364
+ /*
285
+ * always one above the command port */
365
+ * in the reference implementation, the control port is
366
+ * always one above the command port
367
+ */
286
+ port = atoi(mo->command->u.inet.port) + 1;
368
+ port = atoi(mo->command->u.inet.port) + 1;
287
+ mo->control->u.inet.port = g_strdup_printf("%d", port);
369
+ mo->control->u.inet.port = g_strdup_printf("%d", port);
288
+ }
370
+ }
289
+
371
+
290
+ t->opts = opts->u.mssim;
372
+ QAPI_CLONE_MEMBERS(TPMMssimOptions, &t->opts, &opts->u.mssim);
291
+ t->cmd_qc = qio_channel_socket_new();
373
+ t->cmd_qc = qio_channel_socket_new();
292
+ t->ctrl_qc = qio_channel_socket_new();
374
+ t->ctrl_qc = qio_channel_socket_new();
293
+
375
+
294
+ if (qio_channel_socket_connect_sync(t->cmd_qc, mo->command, &errp) < 0)
376
+ if (qio_channel_socket_connect_sync(t->cmd_qc, mo->command, &errp) < 0) {
295
+ goto fail;
377
+ goto fail;
296
+
378
+ }
297
+ if (qio_channel_socket_connect_sync(t->ctrl_qc, mo->control, &errp) < 0)
379
+
298
+ goto fail;
380
+ if (qio_channel_socket_connect_sync(t->ctrl_qc, mo->control, &errp) < 0) {
299
+ qio_channel_close(QIO_CHANNEL(t->ctrl_qc), &errp);
381
+ goto fail;
300
+
382
+ }
301
+ if (!runstate_check(RUN_STATE_INMIGRATE)) {
383
+ qio_channel_close(QIO_CHANNEL(t->ctrl_qc), NULL);
302
+ /* reset the TPM using a power cycle sequence, in case someone
384
+ qio_channel_close(QIO_CHANNEL(t->cmd_qc), NULL);
303
+ * has previously powered it up */
385
+
304
+ sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_OFF, &errp);
305
+ if (sock != 0)
306
+ goto fail;
307
+ sock = tpm_send_ctrl(t, TPM_SIGNAL_POWER_ON, &errp);
308
+ if (sock != 0)
309
+ goto fail;
310
+ sock = tpm_send_ctrl(t, TPM_SIGNAL_NV_ON, &errp);
311
+ if (sock != 0)
312
+ goto fail;
313
+ }
314
+
386
+
315
+ return be;
387
+ return be;
316
+
388
+
317
+ fail:
389
+ fail:
318
+ object_unref(OBJECT(t->ctrl_qc));
390
+ object_unref(OBJECT(t->ctrl_qc));
...
...
347
+ cl->type = TPM_TYPE_MSSIM;
419
+ cl->type = TPM_TYPE_MSSIM;
348
+ cl->opts = tpm_mssim_cmdline_opts;
420
+ cl->opts = tpm_mssim_cmdline_opts;
349
+ cl->desc = "TPM mssim emulator backend driver";
421
+ cl->desc = "TPM mssim emulator backend driver";
350
+ cl->create = tpm_mssim_create;
422
+ cl->create = tpm_mssim_create;
351
+ cl->cancel_cmd = tpm_mssim_cancel_cmd;
423
+ cl->cancel_cmd = tpm_mssim_cancel_cmd;
424
+ cl->startup_tpm = tpm_mssim_startup;
352
+ cl->get_tpm_version = tpm_mssim_get_version;
425
+ cl->get_tpm_version = tpm_mssim_get_version;
353
+ cl->get_buffer_size = tpm_mssim_get_buffer_size;
426
+ cl->get_buffer_size = tpm_mssim_get_buffer_size;
354
+ cl->get_tpm_options = tpm_mssim_get_opts;
427
+ cl->get_tpm_options = tpm_mssim_get_opts;
355
+ cl->handle_request = tpm_mssim_handle_request;
428
+ cl->handle_request = tpm_mssim_handle_request;
356
+}
429
+}
357
+
430
+
358
+static const TypeInfo tpm_mssim_info = {
431
+static const TypeInfo tpm_mssim_info = {
359
+ .name = TYPE_TPM_MSSIM,
432
+ .name = TYPE_TPM_MSSIM,
360
+ .parent = TYPE_TPM_BACKEND,
433
+ .parent = TYPE_TPM_BACKEND,
361
+ .instance_size = sizeof(TPMmssim),
434
+ .instance_size = sizeof(TPMMssim),
362
+ .class_init = tpm_mssim_class_init,
435
+ .class_init = tpm_mssim_class_init,
363
+ .instance_init = tpm_mssim_instance_init,
436
+ .instance_init = tpm_mssim_instance_init,
364
+ .instance_finalize = tpm_mssim_instance_finalize,
437
+ .instance_finalize = tpm_mssim_instance_finalize,
365
+};
438
+};
366
+
439
+
...
...
390
+#define TPM_SIGNAL_POWER_OFF 2
463
+#define TPM_SIGNAL_POWER_OFF 2
391
+#define TPM_SIGNAL_PHYS_PRES_ON 3
464
+#define TPM_SIGNAL_PHYS_PRES_ON 3
392
+#define TPM_SIGNAL_PHYS_PRES_OFF 4
465
+#define TPM_SIGNAL_PHYS_PRES_OFF 4
393
+#define TPM_SIGNAL_HASH_START 5
466
+#define TPM_SIGNAL_HASH_START 5
394
+#define TPM_SIGNAL_HASH_DATA 6
467
+#define TPM_SIGNAL_HASH_DATA 6
395
+ // {uint32_t BufferSize, uint8_t[BufferSize] Buffer}
468
+/* {uint32_t BufferSize, uint8_t[BufferSize] Buffer} */
396
+#define TPM_SIGNAL_HASH_END 7
469
+#define TPM_SIGNAL_HASH_END 7
397
+#define TPM_SEND_COMMAND 8
470
+#define TPM_SEND_COMMAND 8
398
+ // {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} ->
471
+/*
399
+ // {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer}
472
+ * {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} ->
400
+
473
+ * {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer}
474
+ */
401
+#define TPM_SIGNAL_CANCEL_ON 9
475
+#define TPM_SIGNAL_CANCEL_ON 9
402
+#define TPM_SIGNAL_CANCEL_OFF 10
476
+#define TPM_SIGNAL_CANCEL_OFF 10
403
+#define TPM_SIGNAL_NV_ON 11
477
+#define TPM_SIGNAL_NV_ON 11
404
+#define TPM_SIGNAL_NV_OFF 12
478
+#define TPM_SIGNAL_NV_OFF 12
405
+#define TPM_SIGNAL_KEY_CACHE_ON 13
479
+#define TPM_SIGNAL_KEY_CACHE_ON 13
...
...
428
...
502
...
429
503
430
+The QEMU TPM Microsoft Simulator Device
504
+The QEMU TPM Microsoft Simulator Device
431
+---------------------------------------
505
+---------------------------------------
432
+
506
+
433
+The TCG provides a reference implementation for TPM 2.0 written by
507
+The Microsoft Simulator (mssim) is the reference emulation platform
434
+Microsoft (See `ms-tpm-20-ref`_ on github). The reference implementation
508
+for the TCG TPM 2.0 specification. It provides a reference
435
+starts a network server and listens for TPM commands on port 2321 and
509
+implementation for the TPM 2.0 written by Microsoft (See
436
+TPM Platform control commands on port 2322, although these can be
510
+`ms-tpm-20-ref`_ on github). The reference implementation starts a
437
+altered. The QEMU mssim TPM backend talks to this implementation. By
511
+network server and listens for TPM commands on port 2321 and TPM
438
+default it connects to the default ports on localhost:
512
+Platform control commands on port 2322, although these can be altered.
513
+The QEMU mssim TPM backend talks to this implementation. By default
514
+it connects to the default ports on localhost:
439
+
515
+
440
+.. code-block:: console
516
+.. code-block:: console
441
+
517
+
442
+ qemu-system-x86_64 <qemu-options> \
518
+ qemu-system-x86_64 <qemu-options> \
443
+ -tpmdev mssim,id=tpm0 \
519
+ -tpmdev mssim,id=tpm0 \
444
+ -device tpm-crb,tpmdev=tpm0
520
+ -device tpm-crb,tpmdev=tpm0
445
+
521
+
446
+
522
+
447
+Although it can also communicate with a remote host, which must be
523
+Although it can also communicate with a remote host, which must be
448
+specified as a SocketAddress via json on the command line for each of
524
+specified as a SocketAddress via json or dotted keys on the command
449
+the command and control ports:
525
+line for each of the command and control ports:
450
+
526
+
451
+.. code-block:: console
527
+.. code-block:: console
452
+
528
+
453
+ qemu-system-x86_64 <qemu-options> \
529
+ qemu-system-x86_64 <qemu-options> \
454
+ -tpmdev "{'type':'mssim','id':'tpm0','command':{'type':'inet','host':'remote','port':'2321'},'control':{'type':'inet','host':'remote','port':'2322'}}" \
530
+ -tpmdev "{'type':'mssim','id':'tpm0','command':{'type':'inet','host':'remote','port':'2321'},'control':{'type':'inet','host':'remote','port':'2322'}}" \
455
+ -device tpm-crb,tpmdev=tpm0
531
+ -device tpm-crb,tpmdev=tpm0
456
+
532
+
457
+
533
+
458
+The mssim backend supports snapshotting and migration, but the state
534
+The mssim backend supports snapshotting and migration by not resetting
459
+of the Microsoft Simulator server must be preserved (or the server
535
+the TPM on start up and not powering it down on halt if the VM is in
460
+kept running) outside of QEMU for restore to be successful.
536
+migration, but the state of the Microsoft Simulator server must be
537
+preserved (or the server kept running) outside of QEMU for restore to
538
+be successful.
461
+
539
+
462
The QEMU TPM emulator device
540
The QEMU TPM emulator device
463
----------------------------
541
----------------------------
464
542
465
@@ -XXX,XX +XXX,XX @@ the following:
543
@@ -XXX,XX +XXX,XX @@ the following:
466
544
467
.. _SWTPM protocol:
545
.. _SWTPM protocol:
468
https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
546
https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
469
+
547
+
470
+.. _ms-tpm-20-ref:
548
+.. _ms-tpm-20-ref:
471
+ https://github.com/microsoft/ms-tpm-20-ref
549
+ https://github.com/microsoft/ms-tpm-20-ref
472
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
550
diff --git a/qapi/tpm.json b/qapi/tpm.json
473
index XXXXXXX..XXXXXXX 100644
551
index XXXXXXX..XXXXXXX 100644
474
--- a/monitor/hmp-cmds.c
552
--- a/qapi/tpm.json
475
+++ b/monitor/hmp-cmds.c
553
+++ b/qapi/tpm.json
554
@@ -XXX,XX +XXX,XX @@
555
# = TPM (trusted platform module) devices
556
##
557
558
+{ 'include': 'sockets.json' }
559
+
560
##
561
# @TpmModel:
562
#
563
@@ -XXX,XX +XXX,XX @@
564
#
565
# @emulator: Software Emulator TPM type (since 2.11)
566
#
567
+# @mssim: Microsoft TPM Emulator (since 9.0)
568
+#
569
# Since: 1.5
570
##
571
-{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ],
572
+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator', 'mssim' ],
573
'if': 'CONFIG_TPM' }
574
575
##
576
@@ -XXX,XX +XXX,XX @@
577
# .. qmp-example::
578
#
579
# -> { "execute": "query-tpm-types" }
580
-# <- { "return": [ "passthrough", "emulator" ] }
581
+# <- { "return": [ "passthrough", "emulator", "mssim" ] }
582
##
583
{ 'command': 'query-tpm-types', 'returns': ['TpmType'],
584
'if': 'CONFIG_TPM' }
585
@@ -XXX,XX +XXX,XX @@
586
'data': { 'data': 'TPMEmulatorOptions' },
587
'if': 'CONFIG_TPM' }
588
589
+##
590
+# @TPMMssimOptions:
591
+#
592
+# Information for the mssim emulator connection
593
+#
594
+# @command: command socket for the TPM emulator
595
+#
596
+# @control: control socket for the TPM emulator
597
+#
598
+# Since: 9.0
599
+##
600
+{ 'struct': 'TPMMssimOptions',
601
+ 'data': { '*command': 'SocketAddress',
602
+ '*control': 'SocketAddress' },
603
+ 'if': 'CONFIG_TPM' }
604
+
605
##
606
# @TpmTypeOptions:
607
#
608
@@ -XXX,XX +XXX,XX @@
609
# passthrough type
610
# - 'emulator' The configuration options for TPM emulator backend
611
# type
612
+# - 'mssim' The configuration options for TPM emulator mssim type
613
#
614
# Since: 1.5
615
##
616
@@ -XXX,XX +XXX,XX @@
617
'base': { 'type': 'TpmType' },
618
'discriminator': 'type',
619
'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper',
620
- 'emulator': 'TPMEmulatorOptionsWrapper' },
621
+ 'emulator': 'TPMEmulatorOptionsWrapper',
622
+ 'mssim' : 'TPMMssimOptions' },
623
'if': 'CONFIG_TPM' }
624
625
##
626
@@ -XXX,XX +XXX,XX @@
627
'id' : 'str' },
628
'discriminator': 'type',
629
'data': { 'passthrough' : 'TPMPassthroughOptions',
630
- 'emulator': 'TPMEmulatorOptions' },
631
+ 'emulator': 'TPMEmulatorOptions',
632
+ 'mssim': 'TPMMssimOptions' },
633
'if': 'CONFIG_TPM' }
634
635
##
636
diff --git a/system/tpm-hmp-cmds.c b/system/tpm-hmp-cmds.c
637
index XXXXXXX..XXXXXXX 100644
638
--- a/system/tpm-hmp-cmds.c
639
+++ b/system/tpm-hmp-cmds.c
476
@@ -XXX,XX +XXX,XX @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
640
@@ -XXX,XX +XXX,XX @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
477
unsigned int c = 0;
641
unsigned int c = 0;
478
TPMPassthroughOptions *tpo;
642
TPMPassthroughOptions *tpo;
479
TPMEmulatorOptions *teo;
643
TPMEmulatorOptions *teo;
480
+ TPMmssimOptions *tmo;
644
+ TPMMssimOptions *tmo;
481
645
482
info_list = qmp_query_tpm(&err);
646
info_list = qmp_query_tpm(&err);
483
if (err) {
647
if (err) {
484
@@ -XXX,XX +XXX,XX @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
648
@@ -XXX,XX +XXX,XX @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
485
teo = ti->options->u.emulator.data;
649
teo = ti->options->u.emulator.data;
486
monitor_printf(mon, ",chardev=%s", teo->chardev);
650
monitor_printf(mon, ",chardev=%s", teo->chardev);
487
break;
651
break;
488
+ case TPM_TYPE_MSSIM:
652
+ case TPM_TYPE_MSSIM:
489
+ tmo = &ti->options->u.mssim;
653
+ tmo = &ti->options->u.mssim;
490
+ monitor_printf(mon, ",command=%s:%s,control=%s:%s",
654
+ monitor_printf(mon, ",command=%s:%s,control=%s:%s",
491
+ tmo->command->u.inet.host, tmo->command->u.inet.port,
655
+ tmo->command->u.inet.host,
492
+ tmo->control->u.inet.host, tmo->control->u.inet.port);
656
+ tmo->command->u.inet.port,
657
+ tmo->control->u.inet.host,
658
+ tmo->control->u.inet.port);
493
+ break;
659
+ break;
494
case TPM_TYPE__MAX:
660
case TPM_TYPE__MAX:
495
break;
661
break;
496
}
662
}
497
diff --git a/qapi/tpm.json b/qapi/tpm.json
498
index XXXXXXX..XXXXXXX 100644
499
--- a/qapi/tpm.json
500
+++ b/qapi/tpm.json
501
@@ -XXX,XX +XXX,XX @@
502
##
503
# = TPM (trusted platform module) devices
504
##
505
+{ 'include': 'sockets.json' }
506
507
##
508
# @TpmModel:
509
@@ -XXX,XX +XXX,XX @@
510
#
511
# Since: 1.5
512
##
513
-{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ],
514
+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator', 'mssim' ],
515
'if': 'CONFIG_TPM' }
516
517
##
518
@@ -XXX,XX +XXX,XX @@
519
# Example:
520
#
521
# -> { "execute": "query-tpm-types" }
522
-# <- { "return": [ "passthrough", "emulator" ] }
523
+# <- { "return": [ "passthrough", "emulator", "mssim" ] }
524
#
525
##
526
{ 'command': 'query-tpm-types', 'returns': ['TpmType'],
527
@@ -XXX,XX +XXX,XX @@
528
'data': { 'data': 'TPMEmulatorOptions' },
529
'if': 'CONFIG_TPM' }
530
531
+##
532
+# @TPMmssimOptions:
533
+#
534
+# Information for the mssim emulator connection
535
+#
536
+# @command: command socket for the TPM emulator
537
+# @control: control socket for the TPM emulator
538
+#
539
+# Since: 7.2.0
540
+##
541
+{ 'struct': 'TPMmssimOptions',
542
+ 'data': {
543
+ '*command': 'SocketAddress',
544
+ '*control': 'SocketAddress' },
545
+ 'if': 'CONFIG_TPM' }
546
+
547
##
548
# @TpmTypeOptions:
549
#
550
@@ -XXX,XX +XXX,XX @@
551
#
552
# @type: - 'passthrough' The configuration options for the TPM passthrough type
553
# - 'emulator' The configuration options for TPM emulator backend type
554
+# - 'mssim' The configuration options for TPM emulator mssim type
555
#
556
# Since: 1.5
557
##
558
@@ -XXX,XX +XXX,XX @@
559
'base': { 'type': 'TpmType' },
560
'discriminator': 'type',
561
'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper',
562
- 'emulator': 'TPMEmulatorOptionsWrapper' },
563
+ 'emulator': 'TPMEmulatorOptionsWrapper',
564
+ 'mssim' : 'TPMmssimOptions' },
565
'if': 'CONFIG_TPM' }
566
567
##
568
@@ -XXX,XX +XXX,XX @@
569
'id' : 'str' },
570
'discriminator': 'type',
571
'data': { 'passthrough' : 'TPMPassthroughOptions',
572
- 'emulator': 'TPMEmulatorOptions' },
573
+ 'emulator': 'TPMEmulatorOptions',
574
+ 'mssim': 'TPMmssimOptions' },
575
'if': 'CONFIG_TPM' }
576
577
##
578
--
663
--
579
2.35.3
664
2.35.3
diff view generated by jsdifflib