@@ -69,7 +69,7 @@ typedef struct TPMBlobBuffers {
struct TPMEmulator {
TPMBackend parent;
- TPMEmulatorOptions *options;
+ TpmTypeOptions *options;
CharBackend ctrl_chr;
QIOChannel *data_ioc;
TPMVersion tpm_version;
@@ -584,33 +584,28 @@ err_exit:
return -1;
}
-static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
+static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, TpmTypeOptions *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;
- }
+ tpm_emu->options = opts;
+ tpm_emu->data_ioc = NULL;
- dev = qemu_chr_find(value);
+ dev = qemu_chr_find(opts->u.emulator.chardev);
if (!dev) {
- error_report("tpm-emulator: tpm chardev '%s' not found", value);
+ error_report("tpm-emulator: tpm chardev '%s' not found",
+ opts->u.emulator.chardev);
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);
+ opts->u.emulator.chardev);
error_report_err(err);
goto err;
}
- tpm_emu->options->chardev = g_strdup(value);
-
if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
goto err;
}
@@ -621,7 +616,7 @@ static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
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));
+ tpm_emu->options->u.emulator.chardev, strerror(errno));
goto err;
}
@@ -649,7 +644,7 @@ err:
return -1;
}
-static TPMBackend *tpm_emulator_create(QemuOpts *opts)
+static TPMBackend *tpm_emulator_create(TpmTypeOptions *opts)
{
TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
@@ -664,10 +659,9 @@ static TPMBackend *tpm_emulator_create(QemuOpts *opts)
static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
{
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
- TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
+ TpmTypeOptions *options;
- options->type = TPM_TYPE_EMULATOR;
- options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
+ options = QAPI_CLONE(TpmTypeOptions, tpm_emu->options);
return options;
}
@@ -972,7 +966,6 @@ static void tpm_emulator_inst_init(Object *obj)
trace_tpm_emulator_inst_init();
- tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
tpm_emu->cur_locty_number = ~0;
qemu_mutex_init(&tpm_emu->mutex);
tpm_emu->vmstate =
@@ -990,7 +983,7 @@ static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
{
ptm_res res;
- if (!tpm_emu->options->chardev) {
+ if (!tpm_emu->data_ioc) {
/* was never properly initialized */
return;
}
@@ -1015,7 +1008,7 @@ static void tpm_emulator_inst_finalize(Object *obj)
qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
- qapi_free_TPMEmulatorOptions(tpm_emu->options);
+ qapi_free_TpmTypeOptions(tpm_emu->options);
if (tpm_emu->migration_blocker) {
migrate_del_blocker(tpm_emu->migration_blocker);
@@ -41,7 +41,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(TPMPassthruState, TPM_PASSTHROUGH)
struct TPMPassthruState {
TPMBackend parent;
- TPMPassthroughOptions *options;
+ TpmTypeOptions *options;
const char *tpm_dev;
int tpm_fd;
bool tpm_executing;
@@ -214,8 +214,8 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
char *dev;
char path[PATH_MAX];
- if (tpm_pt->options->cancel_path) {
- fd = qemu_open_old(tpm_pt->options->cancel_path, O_WRONLY);
+ if (tpm_pt->options->u.passthrough.cancel_path) {
+ fd = qemu_open_old(tpm_pt->options->u.passthrough.cancel_path, O_WRONLY);
if (fd < 0) {
error_report("tpm_passthrough: Could not open TPM cancel path: %s",
strerror(errno));
@@ -245,30 +245,18 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
if (fd < 0) {
error_report("tpm_passthrough: Could not guess TPM cancel path");
} else {
- tpm_pt->options->cancel_path = g_strdup(path);
+ tpm_pt->options->u.passthrough.cancel_path = g_strdup(path);
}
return fd;
}
static int
-tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
+tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, TpmTypeOptions *opts)
{
- const char *value;
+ tpm_pt->options = opts;
- value = qemu_opt_get(opts, "cancel-path");
- if (value) {
- tpm_pt->options->cancel_path = g_strdup(value);
- tpm_pt->options->has_cancel_path = true;
- }
-
- value = qemu_opt_get(opts, "path");
- if (value) {
- tpm_pt->options->has_path = true;
- tpm_pt->options->path = g_strdup(value);
- }
-
- tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE;
+ tpm_pt->tpm_dev = opts->u.passthrough.has_path ? opts->u.passthrough.path : TPM_PASSTHROUGH_DEFAULT_DEVICE;
tpm_pt->tpm_fd = qemu_open_old(tpm_pt->tpm_dev, O_RDWR);
if (tpm_pt->tpm_fd < 0) {
error_report("Cannot access TPM device using '%s': %s",
@@ -290,11 +278,11 @@ tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
return 0;
}
-static TPMBackend *tpm_passthrough_create(QemuOpts *opts)
+static TPMBackend *tpm_passthrough_create(TpmTypeOptions *tto)
{
Object *obj = object_new(TYPE_TPM_PASSTHROUGH);
- if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), opts)) {
+ if (tpm_passthrough_handle_device_opts(TPM_PASSTHROUGH(obj), tto)) {
object_unref(obj);
return NULL;
}
@@ -320,9 +308,7 @@ static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
{
TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
- options->type = TPM_TYPE_PASSTHROUGH;
- options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
- TPM_PASSTHROUGH(tb)->options);
+ options = QAPI_CLONE(TpmTypeOptions, TPM_PASSTHROUGH(tb)->options);
return options;
}
@@ -346,7 +332,6 @@ static void tpm_passthrough_inst_init(Object *obj)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
- tpm_pt->options = g_new0(TPMPassthroughOptions, 1);
tpm_pt->tpm_fd = -1;
tpm_pt->cancel_fd = -1;
}
@@ -363,7 +348,7 @@ static void tpm_passthrough_inst_finalize(Object *obj)
if (tpm_pt->cancel_fd >= 0) {
qemu_close(tpm_pt->cancel_fd);
}
- qapi_free_TPMPassthroughOptions(tpm_pt->options);
+ qapi_free_TpmTypeOptions(tpm_pt->options);
}
static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
@@ -18,7 +18,7 @@
#ifdef CONFIG_TPM
int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
-int tpm_init(void);
+void tpm_init(void);
void tpm_cleanup(void);
typedef enum TPMVersion {
@@ -57,7 +57,7 @@ struct TPMBackendClass {
/* get a descriptive text of the backend to display to the user */
const char *desc;
- TPMBackend *(*create)(QemuOpts *opts);
+ TPMBackend *(*create)(TpmTypeOptions *tto);
/* start up the TPM on the backend - optional */
int (*startup_tpm)(TPMBackend *t, size_t buffersize);
@@ -863,7 +863,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
switch (ti->options->type) {
case TPM_TYPE_PASSTHROUGH:
- tpo = ti->options->u.passthrough.data;
+ tpo = &ti->options->u.passthrough;
monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
tpo->has_path ? tpo->path : "",
@@ -871,7 +871,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
tpo->has_cancel_path ? tpo->cancel_path : "");
break;
case TPM_TYPE_EMULATOR:
- teo = ti->options->u.emulator.data;
+ teo = &ti->options->u.emulator;
monitor_printf(mon, ",chardev=%s", teo->chardev);
break;
case TPM_TYPE__MAX:
@@ -99,39 +99,23 @@
{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' },
'if': 'CONFIG_TPM' }
-##
-# @TPMPassthroughOptionsWrapper:
-#
-# Since: 1.5
-##
-{ 'struct': 'TPMPassthroughOptionsWrapper',
- 'data': { 'data': 'TPMPassthroughOptions' },
- 'if': 'CONFIG_TPM' }
-
-##
-# @TPMEmulatorOptionsWrapper:
-#
-# Since: 2.11
-##
-{ 'struct': 'TPMEmulatorOptionsWrapper',
- 'data': { 'data': 'TPMEmulatorOptions' },
- 'if': 'CONFIG_TPM' }
-
##
# @TpmTypeOptions:
#
# A union referencing different TPM backend types' configuration options
#
+# @id: identifier of the backend
# @type: - 'passthrough' The configuration options for the TPM passthrough type
# - 'emulator' The configuration options for TPM emulator backend type
#
# Since: 1.5
##
{ 'union': 'TpmTypeOptions',
- 'base': { 'type': 'TpmType' },
+ 'base': { 'type': 'TpmType',
+ 'id': 'str' },
'discriminator': 'type',
- 'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper',
- 'emulator': 'TPMEmulatorOptionsWrapper' },
+ 'data': { 'passthrough' : 'TPMPassthroughOptions',
+ 'emulator': 'TPMEmulatorOptions' },
'if': 'CONFIG_TPM' }
##
@@ -17,14 +17,26 @@
#include "qapi/error.h"
#include "qapi/qapi-commands-tpm.h"
#include "qapi/qmp/qerror.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qapi-visit-tpm.h"
#include "sysemu/tpm_backend.h"
#include "sysemu/tpm.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "qemu/help_option.h"
static QLIST_HEAD(, TPMBackend) tpm_backends =
QLIST_HEAD_INITIALIZER(tpm_backends);
+typedef struct TpmTypeOptionsQueueEntry {
+ TpmTypeOptions *tto;
+ QSIMPLEQ_ENTRY(TpmTypeOptionsQueueEntry) entry;
+} TpmTypeOptionsQueueEntry;
+
+typedef QSIMPLEQ_HEAD(, TpmTypeOptionsQueueEntry) TpmTypeOptionsQueue;
+
+static TpmTypeOptionsQueue tto_queue = QSIMPLEQ_HEAD_INITIALIZER(tto_queue);
+
static const TPMBackendClass *
tpm_be_find_by_type(enum TpmType type)
{
@@ -84,63 +96,36 @@ TPMBackend *qemu_find_tpm_be(const char *id)
return NULL;
}
-static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp)
+static void tpm_init_tpmdev(TpmTypeOptions *tto)
{
- /*
- * Use of error_report() in a function with an Error ** parameter
- * is suspicious. It is okay here. The parameter only exists to
- * make the function usable with qemu_opts_foreach(). It is not
- * actually used.
- */
- const char *value;
- const char *id;
const TPMBackendClass *be;
TPMBackend *drv;
- Error *local_err = NULL;
- int i;
if (!QLIST_EMPTY(&tpm_backends)) {
error_report("Only one TPM is allowed.");
- return 1;
+ exit(1);
}
- id = qemu_opts_id(opts);
- if (id == NULL) {
+ if (!tto->id) {
error_report(QERR_MISSING_PARAMETER, "id");
- return 1;
+ exit(1);
}
- value = qemu_opt_get(opts, "type");
- if (!value) {
- error_report(QERR_MISSING_PARAMETER, "type");
- tpm_display_backend_drivers();
- return 1;
- }
-
- i = qapi_enum_parse(&TpmType_lookup, value, -1, NULL);
- be = i >= 0 ? tpm_be_find_by_type(i) : NULL;
+ be = tto->type >= 0 ? tpm_be_find_by_type(tto->type) : NULL;
if (be == NULL) {
error_report(QERR_INVALID_PARAMETER_VALUE,
"type", "a TPM backend type");
tpm_display_backend_drivers();
- return 1;
- }
-
- /* validate backend specific opts */
- if (!qemu_opts_validate(opts, be->opts, &local_err)) {
- error_report_err(local_err);
- return 1;
+ exit(1);
}
- drv = be->create(opts);
+ drv = be->create(tto);
if (!drv) {
- return 1;
+ exit(1);
}
- drv->id = g_strdup(id);
+ drv->id = g_strdup(tto->id);
QLIST_INSERT_HEAD(&tpm_backends, drv, list);
-
- return 0;
}
/*
@@ -161,14 +146,15 @@ void tpm_cleanup(void)
* Initialize the TPM. Process the tpmdev command line options describing the
* TPM backend.
*/
-int tpm_init(void)
+void tpm_init(void)
{
- if (qemu_opts_foreach(qemu_find_opts("tpmdev"),
- tpm_init_tpmdev, NULL, NULL)) {
- return -1;
- }
+ while (!QSIMPLEQ_EMPTY(&tto_queue)) {
+ TpmTypeOptionsQueueEntry *ttoqe = QSIMPLEQ_FIRST(&tto_queue);
- return 0;
+ QSIMPLEQ_REMOVE_HEAD(&tto_queue, entry);
+ tpm_init_tpmdev(ttoqe->tto);
+ g_free(ttoqe);
+ }
}
/*
@@ -177,16 +163,18 @@ int tpm_init(void)
*/
int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
{
- QemuOpts *opts;
+ Visitor *v;
+ TpmTypeOptionsQueueEntry *toqe;
- if (!strcmp(optarg, "help")) {
+ if (is_help_option(optarg)) {
tpm_display_backend_drivers();
return -1;
}
- opts = qemu_opts_parse_noisily(opts_list, optarg, true);
- if (!opts) {
- return -1;
- }
+ v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
+ toqe = g_new(TpmTypeOptionsQueueEntry, 1);
+ visit_type_TpmTypeOptions(v, NULL, &toqe->tto, &error_fatal);
+ visit_free(v);
+ QSIMPLEQ_INSERT_TAIL(&tto_queue, toqe, entry);
return 0;
}
@@ -1934,9 +1934,7 @@ static void qemu_create_late_backends(void)
object_option_foreach_add(object_create_late);
- if (tpm_init() < 0) {
- exit(1);
- }
+ tpm_init();
qemu_opts_foreach(qemu_find_opts("mon"),
mon_init_func, NULL, &error_fatal);