All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Bottomley <jejb@linux.ibm.com>
To: qemu-devel@nongnu.org
Cc: "Stefan Berger" <stefanb@linux.ibm.com>,
	"Daniel P . Berrangé" <berrange@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>
Subject: [PATCH 1/2] tpm: convert tpmdev options processing to new visitor format
Date: Thu, 15 Dec 2022 13:01:24 -0500	[thread overview]
Message-ID: <20221215180125.24632-2-jejb@linux.ibm.com> (raw)
In-Reply-To: <20221215180125.24632-1-jejb@linux.ibm.com>

From: James Bottomley <James.Bottomley@HansenPartnership.com>

Instead of processing the tpmdev options using the old qemu options,
convert to the new visitor format which also allows the passing of
json on the command line.

Signed-off-by: James Bottomley <jejb@linux.ibm.com>
---
 backends/tpm/tpm_emulator.c    | 35 ++++++--------
 backends/tpm/tpm_passthrough.c | 37 +++++----------
 include/sysemu/tpm.h           |  2 +-
 include/sysemu/tpm_backend.h   |  2 +-
 monitor/hmp-cmds.c             |  4 +-
 qapi/tpm.json                  | 26 ++---------
 softmmu/tpm.c                  | 84 +++++++++++++++-------------------
 softmmu/vl.c                   |  4 +-
 8 files changed, 71 insertions(+), 123 deletions(-)

diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index 49cc3d749d..82988a2986 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -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);
diff --git a/backends/tpm/tpm_passthrough.c b/backends/tpm/tpm_passthrough.c
index 5a2f74db1b..2ce39b2167 100644
--- a/backends/tpm/tpm_passthrough.c
+++ b/backends/tpm/tpm_passthrough.c
@@ -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)
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index fb40e30ff6..55a789ce63 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -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 {
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 8fd3269c11..bcef275688 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -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);
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 01b789a79e..e99447ad68 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -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:
diff --git a/qapi/tpm.json b/qapi/tpm.json
index 4e2ea9756a..d8cbd5ea0e 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -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' }
 
 ##
diff --git a/softmmu/tpm.c b/softmmu/tpm.c
index 578563f05a..22ddfbaaed 100644
--- a/softmmu/tpm.c
+++ b/softmmu/tpm.c
@@ -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;
 }
 
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 5115221efe..773add75cf 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -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);
-- 
2.35.3



  reply	other threads:[~2022-12-15 18:03 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-15 18:01 [PATCH 0/2] tpm: add mssim backend James Bottomley
2022-12-15 18:01 ` James Bottomley [this message]
2022-12-15 18:01 ` [PATCH 2/2] tpm: add backend for mssim James Bottomley
2022-12-15 18:46   ` Stefan Berger
2022-12-15 19:22     ` James Bottomley
2022-12-15 19:35       ` Stefan Berger
2022-12-15 19:40         ` James Bottomley
2022-12-15 19:57           ` Stefan Berger
2022-12-15 20:07             ` James Bottomley
2022-12-15 20:22               ` Stefan Berger
2022-12-15 20:30                 ` James Bottomley
2022-12-15 20:53                   ` Stefan Berger
2022-12-16 10:27                     ` Daniel P. Berrangé
2022-12-16 12:28                       ` Stefan Berger
2022-12-16 12:54                         ` Daniel P. Berrangé
2022-12-16 13:32                           ` Stefan Berger
2022-12-16 13:53                             ` James Bottomley
2022-12-16 14:01                               ` Stefan Berger
2022-12-19 11:49                               ` Stefan Berger
2022-12-19 13:02                                 ` James Bottomley
2022-12-19 14:01                                   ` Stefan Berger
2022-12-16 14:29                             ` Daniel P. Berrangé
2022-12-16 14:55                               ` Stefan Berger
2022-12-16 15:48                                 ` James Bottomley
2022-12-16 16:08                                   ` Stefan Berger
2022-12-16 16:13                                     ` James Bottomley
2022-12-16 16:21                                       ` Stefan Berger
2023-01-09 16:59                               ` Dr. David Alan Gilbert
2023-01-09 17:43                                 ` James Bottomley
2023-01-09 17:52                                   ` Dr. David Alan Gilbert
2023-01-09 17:55                                     ` James Bottomley
2023-01-09 18:34                                       ` Stefan Berger
2023-01-09 18:51                                         ` James Bottomley
2023-01-09 18:54                                           ` Dr. David Alan Gilbert
2023-01-09 18:59                                             ` James Bottomley
2023-01-09 19:01                                           ` Stefan Berger
2023-01-09 21:06                                             ` Stefan Berger
2023-01-10 14:14                                               ` James Bottomley
2023-01-10 14:47                                                 ` Stefan Berger
2023-01-10 14:55                                                   ` James Bottomley
2023-01-10 15:00                                                     ` Stefan Berger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221215180125.24632-2-jejb@linux.ibm.com \
    --to=jejb@linux.ibm.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanb@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.