Message ID | 1338838668-7544-8-git-send-email-stefanb@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
On 06/04/2012 03:37 PM, Stefan Berger wrote: > Enable the passing of a file descriptor via fd=<..> to access the host's > TPM device using the TPM passthrough driver. > > Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> > --- > hmp.c | 7 +++++- > hw/tpm_passthrough.c | 53 ++++++++++++++++++++++++++++++++++++++----------- > qapi-schema.json | 4 ++- > qemu-config.c | 5 ++++ > qemu-options.hx | 11 +++++++-- > tpm.c | 4 +++ > tpm.h | 1 + > 7 files changed, 68 insertions(+), 17 deletions(-) > > diff --git a/hmp.c b/hmp.c > index 9aedaff..3176c74 100644 > --- a/hmp.c > +++ b/hmp.c > @@ -567,10 +567,15 @@ void hmp_info_tpm(Monitor *mon) > TPMInfo *ti = info->value; > monitor_printf(mon, " tpm%d: model=%s\n", > c, ti->model); > - monitor_printf(mon, " \\ %s: type=%s%s%s\n", > + monitor_printf(mon, " \\ %s: type=%s%s%s", > ti->id, ti->type, > ti->has_path ? ",path=" : "", > ti->has_path ? ti->path : ""); > + if (ti->has_fd) { > + monitor_printf(mon, ",fd=%" PRId64, > + ti->fd); > + } > + monitor_printf(mon, "\n"); > c++; > } > qapi_free_TPMInfoList(info_list); > diff --git a/hw/tpm_passthrough.c b/hw/tpm_passthrough.c > index 8914705..44cf272 100644 > --- a/hw/tpm_passthrough.c > +++ b/hw/tpm_passthrough.c > @@ -305,26 +305,54 @@ static int tpm_passthrough_test_tpmdev(int fd) > static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) > { > const char *value; > + struct stat statbuf; > > - value = qemu_opt_get(opts, "path"); > - if (!value) { > - value = TPM_PASSTHROUGH_DEFAULT_DEVICE; > - } > + value = qemu_opt_get(opts, "fd"); > + if (value) { > + if (qemu_opt_get(opts, "path")) { > + error_report("fd= is invalid with path="); > + goto err_exit; > + } > + > + tb->s.tpm_pt->tpm_fd = qemu_parse_fd(value); > + if (tb->s.tpm_pt->tpm_fd < 0) { > + error_report("Illegal file descriptor for TPM device.\n"); > + goto err_exit; > + } > + > + tb->tpm_fd = &tb->s.tpm_pt->tpm_fd; > + } else { > + value = qemu_opt_get(opts, "path"); > + if (!value) { > + value = TPM_PASSTHROUGH_DEFAULT_DEVICE; > + } > > - tb->s.tpm_pt->tpm_dev = g_strdup(value); > + tb->s.tpm_pt->tpm_dev = g_strdup(value); > > - tb->path = g_strdup(tb->s.tpm_pt->tpm_dev); > + tb->path = g_strdup(value); > + > + tb->s.tpm_pt->tpm_fd = open(tb->s.tpm_pt->tpm_dev, O_RDWR); > + if (tb->s.tpm_pt->tpm_fd < 0) { > + error_report("Cannot access TPM device using '%s'.\n", > + tb->s.tpm_pt->tpm_dev); > + goto err_free_parameters; > + } > + } > + > + if (fstat(tb->s.tpm_pt->tpm_fd, &statbuf) != 0) { > + error_report("Cannot determine file descriptor type for TPM " > + "device: %s", strerror(errno)); > + goto err_close_tpmdev; > + } > > - tb->s.tpm_pt->tpm_fd = open(tb->s.tpm_pt->tpm_dev, O_RDWR); > - if (tb->s.tpm_pt->tpm_fd < 0) { > - error_report("Cannot access TPM device using '%s'.\n", > - tb->s.tpm_pt->tpm_dev); > + /* only allow character devices for now */ > + if (!S_ISCHR(statbuf.st_mode)) { > + error_report("TPM file descriptor is not a character device"); > goto err_free_parameters; > } > > if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) { > - error_report("'%s' is not a TPM device.\n", > - tb->s.tpm_pt->tpm_dev); > + error_report("Device is not a TPM.\n"); > goto err_close_tpmdev; > } > > @@ -341,6 +369,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) > g_free(tb->s.tpm_pt->tpm_dev); > tb->s.tpm_pt->tpm_dev = NULL; > > + err_exit: > return 1; > } > > diff --git a/qapi-schema.json b/qapi-schema.json > index 8799322..9d6f664 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -1769,10 +1769,12 @@ > # > # @path: #optional Path to the TPM backend device > # > +# @fd: #optional File descriptor for the TPM backend device > # Since: 1.1 > ## > { 'type': 'TPMInfo', > - 'data': {'model': 'str', 'id': 'str', 'type': 'str', '*path': 'str' } } > + 'data': {'model': 'str', 'id': 'str', 'type': 'str', '*path': 'str', > + '*fd' : 'int' } } > > ## > # @query-tpm > diff --git a/qemu-config.c b/qemu-config.c > index edc8d5d..a5e2677 100644 > --- a/qemu-config.c > +++ b/qemu-config.c > @@ -628,6 +628,11 @@ static QemuOptsList qemu_tpmdev_opts = { > .type = QEMU_OPT_STRING, > .help = "Persistent storage for TPM state", > }, > + { > + .name = "fd", > + .type = QEMU_OPT_STRING, > + .help = "Filedescriptor for accessing the TPM", > + }, > { /* end of list */ } > }, > }; > diff --git a/qemu-options.hx b/qemu-options.hx > index 0b9fa0b..cb9892b 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -2017,8 +2017,9 @@ DEFHEADING() > DEFHEADING(TPM device options:) > > DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \ > - "-tpmdev passthrough,id=id[,path=path]\n" > - " use path to provide path to a character device; default is /dev/tpm0\n", > + "-tpmdev passthrough,id=id[,path=path][,fd=h]\n" > + " use path to provide path to a character device; default is /dev/tpm0\n" > + " use fd to provide a file descriptor to a character device\n", > QEMU_ARCH_ALL) > STEXI > > @@ -2040,7 +2041,7 @@ Use ? to print all available TPM backend types. > qemu -tpmdev ? > @end example > > -@item -tpmdev passthrough, id=@var{id}, path=@var{path} > +@item -tpmdev passthrough, id=@var{id}, path=@var{path}, fd=@var{h} > > (Linux-host only) Enable access to the host's TPM using the passthrough > driver. > @@ -2049,6 +2050,10 @@ driver. > a Linux host this would be @code{/dev/tpm0}. > @option{path} is optional and by default @code{/dev/tpm0} is used. > > +@option{fd} specifies the file descriptor of the host's TPM device. > +@option{fd} and @option{path} are mutually exclusive. > +@option{fd} is optional. > + > Some notes about using the host's TPM with the passthrough driver: > > The TPM device accessed by the passthrough driver must not be > diff --git a/tpm.c b/tpm.c > index 79530c9..64d3140 100644 > --- a/tpm.c > +++ b/tpm.c > @@ -201,6 +201,10 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) > res->path = g_strdup(drv->path); > res->has_path = true; > } > + if (drv->tpm_fd != NULL && *drv->tpm_fd >= 0) { > + res->fd = *drv->tpm_fd; > + res->has_fd = true; > + } > res->type = g_strdup(drv->ops->id); > > return res; > diff --git a/tpm.h b/tpm.h > index bacaff3..00f7600 100644 > --- a/tpm.h > +++ b/tpm.h > @@ -24,6 +24,7 @@ typedef struct TPMBackend { > char *id; > const char *fe_model; > char *path; > + int *tpm_fd; > const TPMDriverOps *ops; > > union { > This patch looks okay to me.
On 06/04/2012 03:37 PM, Stefan Berger wrote: > Enable the passing of a file descriptor via fd=<..> to access the host's > TPM device using the TPM passthrough driver. > > Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> > --- > hmp.c | 7 +++++- > hw/tpm_passthrough.c | 53 ++++++++++++++++++++++++++++++++++++++----------- > qapi-schema.json | 4 ++- > qemu-config.c | 5 ++++ > qemu-options.hx | 11 +++++++-- > tpm.c | 4 +++ > tpm.h | 1 + > 7 files changed, 68 insertions(+), 17 deletions(-) > > diff --git a/hmp.c b/hmp.c > index 9aedaff..3176c74 100644 > --- a/hmp.c > +++ b/hmp.c > @@ -567,10 +567,15 @@ void hmp_info_tpm(Monitor *mon) > TPMInfo *ti = info->value; > monitor_printf(mon, " tpm%d: model=%s\n", > c, ti->model); > - monitor_printf(mon, " \\ %s: type=%s%s%s\n", > + monitor_printf(mon, " \\ %s: type=%s%s%s", > ti->id, ti->type, > ti->has_path ? ",path=" : "", > ti->has_path ? ti->path : ""); > + if (ti->has_fd) { > + monitor_printf(mon, ",fd=%" PRId64, > + ti->fd); > + } > + monitor_printf(mon, "\n"); > c++; > } > qapi_free_TPMInfoList(info_list); > diff --git a/hw/tpm_passthrough.c b/hw/tpm_passthrough.c > index 8914705..44cf272 100644 > --- a/hw/tpm_passthrough.c > +++ b/hw/tpm_passthrough.c > @@ -305,26 +305,54 @@ static int tpm_passthrough_test_tpmdev(int fd) > static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) > { > const char *value; > + struct stat statbuf; > > - value = qemu_opt_get(opts, "path"); > - if (!value) { > - value = TPM_PASSTHROUGH_DEFAULT_DEVICE; > - } > + value = qemu_opt_get(opts, "fd"); > + if (value) { > + if (qemu_opt_get(opts, "path")) { > + error_report("fd= is invalid with path="); > + goto err_exit; > + } > + > + tb->s.tpm_pt->tpm_fd = qemu_parse_fd(value); > + if (tb->s.tpm_pt->tpm_fd < 0) { > + error_report("Illegal file descriptor for TPM device.\n"); > + goto err_exit; > + } > + > + tb->tpm_fd = &tb->s.tpm_pt->tpm_fd; > + } else { > + value = qemu_opt_get(opts, "path"); > + if (!value) { > + value = TPM_PASSTHROUGH_DEFAULT_DEVICE; > + } > > - tb->s.tpm_pt->tpm_dev = g_strdup(value); > + tb->s.tpm_pt->tpm_dev = g_strdup(value); > > - tb->path = g_strdup(tb->s.tpm_pt->tpm_dev); > + tb->path = g_strdup(value); > + > + tb->s.tpm_pt->tpm_fd = open(tb->s.tpm_pt->tpm_dev, O_RDWR); > + if (tb->s.tpm_pt->tpm_fd < 0) { > + error_report("Cannot access TPM device using '%s'.\n", > + tb->s.tpm_pt->tpm_dev); > + goto err_free_parameters; > + } > + } > + > + if (fstat(tb->s.tpm_pt->tpm_fd, &statbuf) != 0) { > + error_report("Cannot determine file descriptor type for TPM " > + "device: %s", strerror(errno)); > + goto err_close_tpmdev; > + } > > - tb->s.tpm_pt->tpm_fd = open(tb->s.tpm_pt->tpm_dev, O_RDWR); > - if (tb->s.tpm_pt->tpm_fd < 0) { > - error_report("Cannot access TPM device using '%s'.\n", > - tb->s.tpm_pt->tpm_dev); > + /* only allow character devices for now */ > + if (!S_ISCHR(statbuf.st_mode)) { > + error_report("TPM file descriptor is not a character device"); > goto err_free_parameters; > } > > if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) { > - error_report("'%s' is not a TPM device.\n", > - tb->s.tpm_pt->tpm_dev); > + error_report("Device is not a TPM.\n"); > goto err_close_tpmdev; > } > > @@ -341,6 +369,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) > g_free(tb->s.tpm_pt->tpm_dev); > tb->s.tpm_pt->tpm_dev = NULL; > > + err_exit: > return 1; > } > > diff --git a/qapi-schema.json b/qapi-schema.json > index 8799322..9d6f664 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -1769,10 +1769,12 @@ > # > # @path: #optional Path to the TPM backend device > # > +# @fd: #optional File descriptor for the TPM backend device > # Since: 1.1 > ## > { 'type': 'TPMInfo', > - 'data': {'model': 'str', 'id': 'str', 'type': 'str', '*path': 'str' } } > + 'data': {'model': 'str', 'id': 'str', 'type': 'str', '*path': 'str', > + '*fd' : 'int' } } > > ## > # @query-tpm > diff --git a/qemu-config.c b/qemu-config.c > index edc8d5d..a5e2677 100644 > --- a/qemu-config.c > +++ b/qemu-config.c > @@ -628,6 +628,11 @@ static QemuOptsList qemu_tpmdev_opts = { > .type = QEMU_OPT_STRING, > .help = "Persistent storage for TPM state", > }, > + { > + .name = "fd", > + .type = QEMU_OPT_STRING, > + .help = "Filedescriptor for accessing the TPM", Filedescriptor needs a space. > + }, > { /* end of list */ } > }, > }; > diff --git a/qemu-options.hx b/qemu-options.hx > index 0b9fa0b..cb9892b 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -2017,8 +2017,9 @@ DEFHEADING() > DEFHEADING(TPM device options:) > > DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \ > - "-tpmdev passthrough,id=id[,path=path]\n" > - " use path to provide path to a character device; default is /dev/tpm0\n", > + "-tpmdev passthrough,id=id[,path=path][,fd=h]\n" > + " use path to provide path to a character device; default is /dev/tpm0\n" > + " use fd to provide a file descriptor to a character device\n", > QEMU_ARCH_ALL) > STEXI > > @@ -2040,7 +2041,7 @@ Use ? to print all available TPM backend types. > qemu -tpmdev ? > @end example > > -@item -tpmdev passthrough, id=@var{id}, path=@var{path} > +@item -tpmdev passthrough, id=@var{id}, path=@var{path}, fd=@var{h} > > (Linux-host only) Enable access to the host's TPM using the passthrough > driver. > @@ -2049,6 +2050,10 @@ driver. > a Linux host this would be @code{/dev/tpm0}. > @option{path} is optional and by default @code{/dev/tpm0} is used. > > +@option{fd} specifies the file descriptor of the host's TPM device. > +@option{fd} and @option{path} are mutually exclusive. > +@option{fd} is optional. > + > Some notes about using the host's TPM with the passthrough driver: > > The TPM device accessed by the passthrough driver must not be > diff --git a/tpm.c b/tpm.c > index 79530c9..64d3140 100644 > --- a/tpm.c > +++ b/tpm.c > @@ -201,6 +201,10 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) > res->path = g_strdup(drv->path); > res->has_path = true; > } > + if (drv->tpm_fd != NULL && *drv->tpm_fd >= 0) { > + res->fd = *drv->tpm_fd; > + res->has_fd = true; > + } Is an else path needed to set res->has_fd = false if there's no tpm_fd?
On 10/03/2012 02:46 PM, Corey Bryant wrote: > > > On 06/04/2012 03:37 PM, Stefan Berger wrote: >> @@ -201,6 +201,10 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) >> res->path = g_strdup(drv->path); >> res->has_path = true; >> } >> + if (drv->tpm_fd != NULL && *drv->tpm_fd >= 0) { >> + res->fd = *drv->tpm_fd; >> + res->has_fd = true; >> + } > > Is an else path needed to set res->has_fd = false if there's no tpm_fd? > res is allocated using g_new0, so all fields are set to 0. With that has_fd is also set to false. Regards, Stefan
diff --git a/hmp.c b/hmp.c index 9aedaff..3176c74 100644 --- a/hmp.c +++ b/hmp.c @@ -567,10 +567,15 @@ void hmp_info_tpm(Monitor *mon) TPMInfo *ti = info->value; monitor_printf(mon, " tpm%d: model=%s\n", c, ti->model); - monitor_printf(mon, " \\ %s: type=%s%s%s\n", + monitor_printf(mon, " \\ %s: type=%s%s%s", ti->id, ti->type, ti->has_path ? ",path=" : "", ti->has_path ? ti->path : ""); + if (ti->has_fd) { + monitor_printf(mon, ",fd=%" PRId64, + ti->fd); + } + monitor_printf(mon, "\n"); c++; } qapi_free_TPMInfoList(info_list); diff --git a/hw/tpm_passthrough.c b/hw/tpm_passthrough.c index 8914705..44cf272 100644 --- a/hw/tpm_passthrough.c +++ b/hw/tpm_passthrough.c @@ -305,26 +305,54 @@ static int tpm_passthrough_test_tpmdev(int fd) static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) { const char *value; + struct stat statbuf; - value = qemu_opt_get(opts, "path"); - if (!value) { - value = TPM_PASSTHROUGH_DEFAULT_DEVICE; - } + value = qemu_opt_get(opts, "fd"); + if (value) { + if (qemu_opt_get(opts, "path")) { + error_report("fd= is invalid with path="); + goto err_exit; + } + + tb->s.tpm_pt->tpm_fd = qemu_parse_fd(value); + if (tb->s.tpm_pt->tpm_fd < 0) { + error_report("Illegal file descriptor for TPM device.\n"); + goto err_exit; + } + + tb->tpm_fd = &tb->s.tpm_pt->tpm_fd; + } else { + value = qemu_opt_get(opts, "path"); + if (!value) { + value = TPM_PASSTHROUGH_DEFAULT_DEVICE; + } - tb->s.tpm_pt->tpm_dev = g_strdup(value); + tb->s.tpm_pt->tpm_dev = g_strdup(value); - tb->path = g_strdup(tb->s.tpm_pt->tpm_dev); + tb->path = g_strdup(value); + + tb->s.tpm_pt->tpm_fd = open(tb->s.tpm_pt->tpm_dev, O_RDWR); + if (tb->s.tpm_pt->tpm_fd < 0) { + error_report("Cannot access TPM device using '%s'.\n", + tb->s.tpm_pt->tpm_dev); + goto err_free_parameters; + } + } + + if (fstat(tb->s.tpm_pt->tpm_fd, &statbuf) != 0) { + error_report("Cannot determine file descriptor type for TPM " + "device: %s", strerror(errno)); + goto err_close_tpmdev; + } - tb->s.tpm_pt->tpm_fd = open(tb->s.tpm_pt->tpm_dev, O_RDWR); - if (tb->s.tpm_pt->tpm_fd < 0) { - error_report("Cannot access TPM device using '%s'.\n", - tb->s.tpm_pt->tpm_dev); + /* only allow character devices for now */ + if (!S_ISCHR(statbuf.st_mode)) { + error_report("TPM file descriptor is not a character device"); goto err_free_parameters; } if (tpm_passthrough_test_tpmdev(tb->s.tpm_pt->tpm_fd)) { - error_report("'%s' is not a TPM device.\n", - tb->s.tpm_pt->tpm_dev); + error_report("Device is not a TPM.\n"); goto err_close_tpmdev; } @@ -341,6 +369,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) g_free(tb->s.tpm_pt->tpm_dev); tb->s.tpm_pt->tpm_dev = NULL; + err_exit: return 1; } diff --git a/qapi-schema.json b/qapi-schema.json index 8799322..9d6f664 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1769,10 +1769,12 @@ # # @path: #optional Path to the TPM backend device # +# @fd: #optional File descriptor for the TPM backend device # Since: 1.1 ## { 'type': 'TPMInfo', - 'data': {'model': 'str', 'id': 'str', 'type': 'str', '*path': 'str' } } + 'data': {'model': 'str', 'id': 'str', 'type': 'str', '*path': 'str', + '*fd' : 'int' } } ## # @query-tpm diff --git a/qemu-config.c b/qemu-config.c index edc8d5d..a5e2677 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -628,6 +628,11 @@ static QemuOptsList qemu_tpmdev_opts = { .type = QEMU_OPT_STRING, .help = "Persistent storage for TPM state", }, + { + .name = "fd", + .type = QEMU_OPT_STRING, + .help = "Filedescriptor for accessing the TPM", + }, { /* end of list */ } }, }; diff --git a/qemu-options.hx b/qemu-options.hx index 0b9fa0b..cb9892b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2017,8 +2017,9 @@ DEFHEADING() DEFHEADING(TPM device options:) DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \ - "-tpmdev passthrough,id=id[,path=path]\n" - " use path to provide path to a character device; default is /dev/tpm0\n", + "-tpmdev passthrough,id=id[,path=path][,fd=h]\n" + " use path to provide path to a character device; default is /dev/tpm0\n" + " use fd to provide a file descriptor to a character device\n", QEMU_ARCH_ALL) STEXI @@ -2040,7 +2041,7 @@ Use ? to print all available TPM backend types. qemu -tpmdev ? @end example -@item -tpmdev passthrough, id=@var{id}, path=@var{path} +@item -tpmdev passthrough, id=@var{id}, path=@var{path}, fd=@var{h} (Linux-host only) Enable access to the host's TPM using the passthrough driver. @@ -2049,6 +2050,10 @@ driver. a Linux host this would be @code{/dev/tpm0}. @option{path} is optional and by default @code{/dev/tpm0} is used. +@option{fd} specifies the file descriptor of the host's TPM device. +@option{fd} and @option{path} are mutually exclusive. +@option{fd} is optional. + Some notes about using the host's TPM with the passthrough driver: The TPM device accessed by the passthrough driver must not be diff --git a/tpm.c b/tpm.c index 79530c9..64d3140 100644 --- a/tpm.c +++ b/tpm.c @@ -201,6 +201,10 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) res->path = g_strdup(drv->path); res->has_path = true; } + if (drv->tpm_fd != NULL && *drv->tpm_fd >= 0) { + res->fd = *drv->tpm_fd; + res->has_fd = true; + } res->type = g_strdup(drv->ops->id); return res; diff --git a/tpm.h b/tpm.h index bacaff3..00f7600 100644 --- a/tpm.h +++ b/tpm.h @@ -24,6 +24,7 @@ typedef struct TPMBackend { char *id; const char *fe_model; char *path; + int *tpm_fd; const TPMDriverOps *ops; union {
Enable the passing of a file descriptor via fd=<..> to access the host's TPM device using the TPM passthrough driver. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> --- hmp.c | 7 +++++- hw/tpm_passthrough.c | 53 ++++++++++++++++++++++++++++++++++++++----------- qapi-schema.json | 4 ++- qemu-config.c | 5 ++++ qemu-options.hx | 11 +++++++-- tpm.c | 4 +++ tpm.h | 1 + 7 files changed, 68 insertions(+), 17 deletions(-)