@@ -583,33 +583,29 @@ 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,
+ TpmCreateOptions *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 = QAPI_CLONE(TPMEmulatorOptions, &opts->u.emulator);
+ 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;
}
@@ -648,7 +644,7 @@ err:
return -1;
}
-static TPMBackend *tpm_emulator_create(QemuOpts *opts)
+static TPMBackend *tpm_emulator_create(TpmCreateOptions *opts)
{
TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
@@ -971,7 +967,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 =
@@ -989,7 +984,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;
}
@@ -252,21 +252,13 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
}
static int
-tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts)
+tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt,
+ TpmCreateOptions *opts)
{
- const char *value;
+ tpm_pt->options = QAPI_CLONE(TPMPassthroughOptions, &opts->u.passthrough);
- value = qemu_opt_get(opts, "cancel-path");
- if (value) {
- tpm_pt->options->cancel_path = g_strdup(value);
- }
-
- value = qemu_opt_get(opts, "path");
- if (value) {
- tpm_pt->options->path = g_strdup(value);
- }
-
- tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE;
+ tpm_pt->tpm_dev = opts->u.passthrough.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",
@@ -288,11 +280,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(TpmCreateOptions *tco)
{
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), tco)) {
object_unref(obj);
return NULL;
}
@@ -344,7 +336,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;
}
@@ -17,8 +17,8 @@
#ifdef CONFIG_TPM
-int tpm_config_parse(QemuOptsList *opts_list, const char *optarg);
-int tpm_init(void);
+void tpm_config_parse(const char *optarg);
+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)(TpmCreateOptions *tco);
/* start up the TPM on the backend - optional */
int (*startup_tpm)(TPMBackend *t, size_t buffersize);
@@ -138,6 +138,25 @@
'emulator': 'TPMEmulatorOptionsWrapper' },
'if': 'CONFIG_TPM' }
+##
+# @TpmCreateOptions:
+#
+# A union referencing different TPM backend types' configuration options
+# without the wrapper to be usable by visitors.
+#
+# @type: - 'passthrough' The configuration options for the TPM passthrough type
+# - 'emulator' The configuration options for TPM emulator backend type
+#
+# Since: 7.2
+##
+{ 'union': 'TpmCreateOptions',
+ 'base': { 'type': 'TpmType',
+ 'id' : 'str' },
+ 'discriminator': 'type',
+ 'data': { 'passthrough' : 'TPMPassthroughOptions',
+ 'emulator': 'TPMEmulatorOptions' },
+ 'if': 'CONFIG_TPM' }
+
##
# @TPMInfo:
#
@@ -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 TpmCreateOptionsQueueEntry {
+ TpmCreateOptions *tco;
+ QSIMPLEQ_ENTRY(TpmCreateOptionsQueueEntry) entry;
+} TpmCreateOptionsQueueEntry;
+
+typedef QSIMPLEQ_HEAD(, TpmCreateOptionsQueueEntry) TpmCreateOptionsQueue;
+
+static TpmCreateOptionsQueue tco_queue = QSIMPLEQ_HEAD_INITIALIZER(tco_queue);
+
static const TPMBackendClass *
tpm_be_find_by_type(enum TpmType type)
{
@@ -84,63 +96,31 @@ 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(TpmCreateOptions *tco)
{
- /*
- * 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) {
- error_report(QERR_MISSING_PARAMETER, "id");
- return 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 = tco->type >= 0 ? tpm_be_find_by_type(tco->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(tco);
if (!drv) {
- return 1;
+ exit(1);
}
- drv->id = g_strdup(id);
+ drv->id = g_strdup(tco->id);
QLIST_INSERT_HEAD(&tpm_backends, drv, list);
-
- return 0;
}
/*
@@ -161,33 +141,36 @@ 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(&tco_queue)) {
+ TpmCreateOptionsQueueEntry *tcoqe = QSIMPLEQ_FIRST(&tco_queue);
- return 0;
+ QSIMPLEQ_REMOVE_HEAD(&tco_queue, entry);
+ tpm_init_tpmdev(tcoqe->tco);
+ qapi_free_TpmCreateOptions(tcoqe->tco);
+ g_free(tcoqe);
+ }
}
/*
* Parse the TPM configuration options.
* To display all available TPM backends the user may use '-tpmdev help'
*/
-int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
+void tpm_config_parse(const char *optarg)
{
- QemuOpts *opts;
+ Visitor *v;
+ TpmCreateOptionsQueueEntry *tcqe;
- 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;
+ exit(0);
}
- return 0;
+ v = qobject_input_visitor_new_str(optarg, "type", &error_fatal);
+ tcqe = g_new(TpmCreateOptionsQueueEntry, 1);
+ visit_type_TpmCreateOptions(v, NULL, &tcqe->tco, &error_fatal);
+ visit_free(v);
+ QSIMPLEQ_INSERT_TAIL(&tco_queue, tcqe, entry);
}
/*
@@ -328,16 +328,6 @@ static QemuOptsList qemu_object_opts = {
},
};
-static QemuOptsList qemu_tpmdev_opts = {
- .name = "tpmdev",
- .implied_opt_name = "type",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_tpmdev_opts.head),
- .desc = {
- /* options are defined in the TPM backends */
- { /* end of list */ }
- },
-};
-
static QemuOptsList qemu_overcommit_opts = {
.name = "overcommit",
.head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head),
@@ -1987,9 +1977,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);
@@ -2726,7 +2714,6 @@ void qemu_init(int argc, char **argv)
qemu_add_opts(&qemu_boot_opts);
qemu_add_opts(&qemu_add_fd_opts);
qemu_add_opts(&qemu_object_opts);
- qemu_add_opts(&qemu_tpmdev_opts);
qemu_add_opts(&qemu_overcommit_opts);
qemu_add_opts(&qemu_msg_opts);
qemu_add_opts(&qemu_name_opts);
@@ -2970,9 +2957,7 @@ void qemu_init(int argc, char **argv)
break;
#ifdef CONFIG_TPM
case QEMU_OPTION_tpmdev:
- if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) {
- exit(1);
- }
+ tpm_config_parse(optarg);
break;
#endif
case QEMU_OPTION_mempath: