[U-Boot] [PATCH v2 05/19] tpm: prepare support for TPMv2 commands

Simon Glass sjg at chromium.org
Thu Mar 29 22:42:06 UTC 2018


Hi Miquel,

On 29 March 2018 at 15:43, Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> Later choice between v1 and v2 compliant functions will be handled by a
> global value in lib/tpm.c that will be accessible through set/get
> accessors from lib/cmd.c.
>
> This global value is set during the initialization phase if the TPM2
> handle is given to the init command.
>
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  cmd/tpm.c     | 37 +++++++++++++++++++++-----
>  include/tpm.h | 20 ++++++++++++++
>  lib/tpm.c     | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 131 insertions(+), 9 deletions(-)
>
> diff --git a/cmd/tpm.c b/cmd/tpm.c
> index f456396d75..1d32028b64 100644
> --- a/cmd/tpm.c
> +++ b/cmd/tpm.c
> @@ -89,12 +89,16 @@ static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr)
>   */
>  static int report_return_code(int return_code)
>  {
> -       if (return_code) {
> -               printf("Error: %d\n", return_code);
> -               return CMD_RET_FAILURE;
> -       } else {
> +       if (!return_code)
>                 return CMD_RET_SUCCESS;
> -       }
> +
> +       if (return_code == -EOPNOTSUPP)
> +               printf("TPMv%d error: unavailable command with this spec\n",
> +                      tpm_get_specification());
> +       else
> +               printf("TPM error: %d\n", return_code);
> +
> +       return CMD_RET_FAILURE;
>  }
>
>  /**
> @@ -427,6 +431,24 @@ static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag,
>         return report_return_code(rc);
>  }
>
> +static int do_tpm_init(cmd_tbl_t *cmdtp, int flag,
> +                      int argc, char * const argv[])
> +{
> +       if (argc > 2)
> +               return CMD_RET_USAGE;
> +
> +       if (argc == 2) {
> +               if (!strcasecmp("TPM1", argv[1]))
> +                       tpm_set_specification(1);
> +               else if (!strcasecmp("TPM2", argv[1]))
> +                       tpm_set_specification(2);
> +               else
> +                       return CMD_RET_USAGE;
> +       }
> +

I don't like the idea of setting a global before calling tpm_init().
Can we instead make it an arg to tpm_init()?

Also, instead of 1 and 2, can you create an enum?

> +       return report_return_code(tpm_init());
> +}
> +
>  #define TPM_COMMAND_NO_ARG(cmd)                                \
>  static int do_##cmd(cmd_tbl_t *cmdtp, int flag,                \
>                 int argc, char * const argv[])          \
> @@ -436,7 +458,6 @@ static int do_##cmd(cmd_tbl_t *cmdtp, int flag,             \
>         return report_return_code(cmd());               \
>  }
>
> -TPM_COMMAND_NO_ARG(tpm_init)
>  TPM_COMMAND_NO_ARG(tpm_self_test_full)
>  TPM_COMMAND_NO_ARG(tpm_continue_self_test)
>  TPM_COMMAND_NO_ARG(tpm_force_clear)
> @@ -902,8 +923,10 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
>  "    - Issue TPM command <cmd> with arguments <args...>.\n"
>  "Admin Startup and State Commands:\n"
>  "  info - Show information about the TPM\n"
> -"  init\n"
> +"  init [<type>]\n"
>  "    - Put TPM into a state where it waits for 'startup' command.\n"
> +"      <type> is one of TPM1 (default) or TPM2. This choice impacts the way\n"
> +"      other functions will behave.\n"
>  "  startup mode\n"
>  "    - Issue TPM_Starup command.  <mode> is one of TPM_ST_CLEAR,\n"
>  "      TPM_ST_STATE, and TPM_ST_DEACTIVATED.\n"
> diff --git a/include/tpm.h b/include/tpm.h
> index 760d94865c..0ec3428ea4 100644
> --- a/include/tpm.h
> +++ b/include/tpm.h
> @@ -30,6 +30,11 @@ enum tpm_startup_type {
>         TPM_ST_DEACTIVATED      = 0x0003,
>  };
>
> +enum tpm2_startup_types {

Please add a comment as to what this is for.

> +       TPM2_SU_CLEAR   = 0x0000,
> +       TPM2_SU_STATE   = 0x0001,
> +};
> +
>  enum tpm_physical_presence {
>         TPM_PHYSICAL_PRESENCE_HW_DISABLE        = 0x0200,
>         TPM_PHYSICAL_PRESENCE_CMD_DISABLE       = 0x0100,
> @@ -417,6 +422,21 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size,
>   */
>  int tpm_init(void);
>
> +/**
> + * Assign a value to the global is_nfcv2 boolean to discriminate in the lib
> + * between the available specifications.
> + *
> + * @version: 1 or 2, depending on the supported specification
> + */
> +int tpm_set_specification(int version);
> +
> +/**
> + * Return the current value of the specification.
> + *
> + * @return: 1 or 2, depending on the supported specification
> + */
> +int tpm_get_specification(void);
> +
>  /**
>   * Issue a TPM_Startup command.
>   *
> diff --git a/lib/tpm.c b/lib/tpm.c
> index 99556b1cf6..38b76b4961 100644
> --- a/lib/tpm.c
> +++ b/lib/tpm.c
> @@ -15,6 +15,9 @@
>  /* Internal error of TPM command library */
>  #define TPM_LIB_ERROR  ((uint32_t)~0u)
>
> +/* Global boolean to discriminate TPMv2.x from TPMv1.x functions */
> +static bool is_tpmv2;

Can this go in the TPM uclass as uclass-private data? See struct
uclass member 'priv'.

> +
>  /* Useful constants */
>  enum {
>         COMMAND_BUFFER_SIZE             = 256,
> @@ -262,6 +265,26 @@ static uint32_t tpm_sendrecv_command(const void *command,
>         return tpm_return_code(response);
>  }
>
> +int tpm_set_specification(int version)
> +{
> +       if (version == 1) {
> +               debug("TPM complies to the v1.x specification\n");
> +               is_tpmv2 = false;
> +       } else if (version == 2) {
> +               debug("TPM complies to the v2.x specification\n");
> +               is_tpmv2 = true;
> +       } else {
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +
> +int tpm_get_specification(void)
> +{
> +       return is_tpmv2 ? 2 : 1;
> +}
> +
>  int tpm_init(void)
>  {
>         int err;
> @@ -338,6 +361,9 @@ uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
>         const size_t size_offset = 77;
>         uint8_t buf[COMMAND_BUFFER_SIZE];
>
> +       if (is_tpmv2)
> +               return -EOPNOTSUPP;
> +
>         if (pack_byte_string(buf, sizeof(buf), "sddd",
>                                 0, command, sizeof(command),
>                                 index_offset, index,
> @@ -362,6 +388,9 @@ uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
>         uint32_t data_size;
>         uint32_t err;
>
> +       if (is_tpmv2)
> +               return -EOPNOTSUPP;

This return code should be mentioned in the header file for these functions.

[...]

Regards,
Simon


More information about the U-Boot mailing list