diff mbox series

[RFC,v2,1/2] optee: obtain emmc rpmb info from dt

Message ID 20210124093946.103018-1-igor.opaniuk@gmail.com
State Changes Requested
Delegated to: Peng Fan
Headers show
Series [RFC,v2,1/2] optee: obtain emmc rpmb info from dt | expand

Commit Message

Igor Opaniuk Jan. 24, 2021, 9:39 a.m. UTC
From: Igor Opaniuk <igor.opaniuk@foundries.io>

Add support for rpmb-dev property in optee node.
Prioritize that provided eMMC info from DT for RPMB operations over
the one provided by OP-TEE OS core in RPC calls.

Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
---

Changes in v2:
- Return NULL instead of ERR_PTR(-ENXIO) in get_rpmb_dev in case there
  is no rpmb-dev property or somemithing went wrong

 drivers/tee/optee/core.c          | 33 +++++++++++++++++
 drivers/tee/optee/optee_private.h |  2 +-
 drivers/tee/optee/rpmb.c          | 60 ++++++++++++++++++-------------
 3 files changed, 70 insertions(+), 25 deletions(-)

Comments

Jens Wiklander Jan. 25, 2021, 8:50 a.m. UTC | #1
Hi Igor,

On Sun, Jan 24, 2021 at 11:39:45AM +0200, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@foundries.io>
> 
> Add support for rpmb-dev property in optee node.
> Prioritize that provided eMMC info from DT for RPMB operations over
> the one provided by OP-TEE OS core in RPC calls.
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
> ---
> 
> Changes in v2:
> - Return NULL instead of ERR_PTR(-ENXIO) in get_rpmb_dev in case there
>   is no rpmb-dev property or somemithing went wrong
> 
>  drivers/tee/optee/core.c          | 33 +++++++++++++++++
>  drivers/tee/optee/optee_private.h |  2 +-
>  drivers/tee/optee/rpmb.c          | 60 ++++++++++++++++++-------------
>  3 files changed, 70 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> index b898c32edc..828ab9b00a 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -12,6 +12,7 @@
>  #include <linux/arm-smccc.h>
>  #include <linux/err.h>
>  #include <linux/io.h>
> +#include <mmc.h>
>  
>  #include "optee_smc.h"
>  #include "optee_msg.h"
> @@ -607,14 +608,46 @@ static optee_invoke_fn *get_invoke_func(struct udevice *dev)
>  	return ERR_PTR(-EINVAL);
>  }
>  
> +static struct mmc *get_rpmb_dev(struct udevice *dev)
> +{
> +	struct udevice *mmc_dev;
> +	const fdt32_t *phandle_p;
> +	u32 phandle;
> +	int ret = 0;
> +
> +	debug("optee: looking for rpmb device in DT.\n");
> +
> +	phandle_p  = ofnode_get_property(dev_ofnode(dev),
> +					 "rpmb-dev", NULL);
> +	if (!phandle_p) {
> +		debug("optee: missing \"rpmb-dev\" property\n");

With this we'll complain in the log each time "rpmb-dev" isn't found
even when OP-TEE isn't configured to use RPMB. This might cause some
confusion.

Cheers,
Jens

> +		return NULL;
> +	}
> +
> +	phandle = fdt32_to_cpu(*phandle_p);
> +
> +	ret = uclass_get_device_by_phandle_id(UCLASS_MMC, phandle, &mmc_dev);
> +	if (ret) {
> +		printf("optee: invalid phandle value in \"rpmb-dev\".\n");
> +		return NULL;
> +	}
> +
> +	debug("optee: using phandle %d from \"rpmd-dev\" property.\n",
> +	      phandle);
> +	return mmc_get_mmc_dev(mmc_dev);
> +}
> +
>  static int optee_of_to_plat(struct udevice *dev)
>  {
>  	struct optee_pdata *pdata = dev_get_plat(dev);
> +	struct optee_private *priv = dev_get_priv(dev);
>  
>  	pdata->invoke_fn = get_invoke_func(dev);
>  	if (IS_ERR(pdata->invoke_fn))
>  		return PTR_ERR(pdata->invoke_fn);
>  
> +	priv->rpmb_mmc = get_rpmb_dev(dev);
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index 1f07a27ee4..8e5a280622 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -19,8 +19,8 @@
>   */
>  struct optee_private {
>  	struct mmc *rpmb_mmc;
> -	int rpmb_dev_id;
>  	int rpmb_original_part;
> +	bool rpmb_inited;
>  };
>  
>  struct optee_msg_arg;
> diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
> index 0804fc963c..0137c44be1 100644
> --- a/drivers/tee/optee/rpmb.c
> +++ b/drivers/tee/optee/rpmb.c
> @@ -45,55 +45,67 @@ static void release_mmc(struct optee_private *priv)
>  {
>  	int rc;
>  
> -	if (!priv->rpmb_mmc)
> +	if (!priv->rpmb_mmc || !priv->rpmb_inited)
>  		return;
>  
> -	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
> -				      priv->rpmb_original_part);
> +	rc = mmc_switch_part(priv->rpmb_mmc, priv->rpmb_original_part);
>  	if (rc)
>  		debug("%s: blk_select_hwpart_devnum() failed: %d\n",
>  		      __func__, rc);
>  
> -	priv->rpmb_mmc = NULL;
> +	priv->rpmb_inited = false;
> +}
> +
> +static int check_mmc(struct mmc *mmc)
> +{
> +	if (!mmc) {
> +		debug("Cannot find RPMB device\n");
> +		return -ENODEV;
> +	}
> +	if (!(mmc->version & MMC_VERSION_MMC)) {
> +		debug("Device id is not an eMMC device\n");
> +		return -ENODEV;
> +	}
> +	if (mmc->version < MMC_VERSION_4_41) {
> +		debug("RPMB is not supported before version 4.41\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
>  }
>  
>  static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
>  {
> -	struct mmc *mmc;
>  	int rc;
>  
> -	if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
> +	if (priv->rpmb_mmc && priv->rpmb_inited)
>  		return priv->rpmb_mmc;
>  
>  	release_mmc(priv);
>  
> -	mmc = find_mmc_device(dev_id);
> -	if (!mmc) {
> -		debug("Cannot find RPMB device\n");
> -		return NULL;
> -	}
> -	if (!(mmc->version & MMC_VERSION_MMC)) {
> -		debug("Device id %d is not an eMMC device\n", dev_id);
> -		return NULL;
> -	}
> -	if (mmc->version < MMC_VERSION_4_41) {
> -		debug("Device id %d: RPMB not supported before version 4.41\n",
> -		      dev_id);
> +	/*
> +	 * Check if priv->rpmb_mmc was already set from DT node,
> +	 * otherwise use dev_id provided by OP-TEE OS
> +	 * and find mmc device by its dev_id
> +	 */
> +	if (!priv->rpmb_mmc)
> +		priv->rpmb_mmc = find_mmc_device(dev_id);
> +
> +	rc = check_mmc(priv->rpmb_mmc);
> +	if (rc)
>  		return NULL;
> -	}
>  
> -	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
> +	priv->rpmb_original_part = mmc_get_blk_desc(priv->rpmb_mmc)->hwpart;
>  
> -	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
> +	rc = mmc_switch_part(priv->rpmb_mmc, MMC_PART_RPMB);
>  	if (rc) {
>  		debug("Device id %d: cannot select RPMB partition: %d\n",
>  		      dev_id, rc);
>  		return NULL;
>  	}
>  
> -	priv->rpmb_mmc = mmc;
> -	priv->rpmb_dev_id = dev_id;
> -	return mmc;
> +	priv->rpmb_inited = true;
> +	return priv->rpmb_mmc;
>  }
>  
>  static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
> -- 
> 2.25.1
>
Igor Opaniuk Jan. 25, 2021, 11:49 a.m. UTC | #2
Hi Jens,

On Mon, Jan 25, 2021 at 10:50 AM Jens Wiklander
<jens.wiklander@linaro.org> wrote:
>
> Hi Igor,
>
> On Sun, Jan 24, 2021 at 11:39:45AM +0200, Igor Opaniuk wrote:
> > From: Igor Opaniuk <igor.opaniuk@foundries.io>
> >
> > Add support for rpmb-dev property in optee node.
> > Prioritize that provided eMMC info from DT for RPMB operations over
> > the one provided by OP-TEE OS core in RPC calls.
> >
> > Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
> > ---
> >
> > Changes in v2:
> > - Return NULL instead of ERR_PTR(-ENXIO) in get_rpmb_dev in case there
> >   is no rpmb-dev property or somemithing went wrong
> >
> >  drivers/tee/optee/core.c          | 33 +++++++++++++++++
> >  drivers/tee/optee/optee_private.h |  2 +-
> >  drivers/tee/optee/rpmb.c          | 60 ++++++++++++++++++-------------
> >  3 files changed, 70 insertions(+), 25 deletions(-)
> >
> > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> > index b898c32edc..828ab9b00a 100644
> > --- a/drivers/tee/optee/core.c
> > +++ b/drivers/tee/optee/core.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/arm-smccc.h>
> >  #include <linux/err.h>
> >  #include <linux/io.h>
> > +#include <mmc.h>
> >
> >  #include "optee_smc.h"
> >  #include "optee_msg.h"
> > @@ -607,14 +608,46 @@ static optee_invoke_fn *get_invoke_func(struct udevice *dev)
> >       return ERR_PTR(-EINVAL);
> >  }
> >
> > +static struct mmc *get_rpmb_dev(struct udevice *dev)
> > +{
> > +     struct udevice *mmc_dev;
> > +     const fdt32_t *phandle_p;
> > +     u32 phandle;
> > +     int ret = 0;
> > +
> > +     debug("optee: looking for rpmb device in DT.\n");
> > +
> > +     phandle_p  = ofnode_get_property(dev_ofnode(dev),
> > +                                      "rpmb-dev", NULL);
> > +     if (!phandle_p) {
> > +             debug("optee: missing \"rpmb-dev\" property\n");
>
> With this we'll complain in the log each time "rpmb-dev" isn't found
> even when OP-TEE isn't configured to use RPMB. This might cause some
> confusion.

Sure I'll wrap with "if (IS_ENABLED(CONFIG_SUPPORT_EMMC_RPMB))"
get_rpmb_dev() invocation in optee_of_to_plat() .

But as it's just a debug message, I would prefer to keep it for
debugging purposes
(I can adjust it, adding the phrase that the driver will use OP-TEE
provided dev id instead).

> Cheers,
> Jens
>
> > +             return NULL;
> > +     }
> > +
> > +     phandle = fdt32_to_cpu(*phandle_p);
> > +
> > +     ret = uclass_get_device_by_phandle_id(UCLASS_MMC, phandle, &mmc_dev);
> > +     if (ret) {
> > +             printf("optee: invalid phandle value in \"rpmb-dev\".\n");
> > +             return NULL;
> > +     }
> > +
> > +     debug("optee: using phandle %d from \"rpmd-dev\" property.\n",
> > +           phandle);
> > +     return mmc_get_mmc_dev(mmc_dev);
> > +}
> > +
> >  static int optee_of_to_plat(struct udevice *dev)
> >  {
> >       struct optee_pdata *pdata = dev_get_plat(dev);
> > +     struct optee_private *priv = dev_get_priv(dev);
> >
> >       pdata->invoke_fn = get_invoke_func(dev);
> >       if (IS_ERR(pdata->invoke_fn))
> >               return PTR_ERR(pdata->invoke_fn);
> >
> > +     priv->rpmb_mmc = get_rpmb_dev(dev);
> > +
> >       return 0;
> >  }
> >
> > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > index 1f07a27ee4..8e5a280622 100644
> > --- a/drivers/tee/optee/optee_private.h
> > +++ b/drivers/tee/optee/optee_private.h
> > @@ -19,8 +19,8 @@
> >   */
> >  struct optee_private {
> >       struct mmc *rpmb_mmc;
> > -     int rpmb_dev_id;
> >       int rpmb_original_part;
> > +     bool rpmb_inited;
> >  };
> >
> >  struct optee_msg_arg;
> > diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
> > index 0804fc963c..0137c44be1 100644
> > --- a/drivers/tee/optee/rpmb.c
> > +++ b/drivers/tee/optee/rpmb.c
> > @@ -45,55 +45,67 @@ static void release_mmc(struct optee_private *priv)
> >  {
> >       int rc;
> >
> > -     if (!priv->rpmb_mmc)
> > +     if (!priv->rpmb_mmc || !priv->rpmb_inited)
> >               return;
> >
> > -     rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
> > -                                   priv->rpmb_original_part);
> > +     rc = mmc_switch_part(priv->rpmb_mmc, priv->rpmb_original_part);
> >       if (rc)
> >               debug("%s: blk_select_hwpart_devnum() failed: %d\n",
> >                     __func__, rc);
> >
> > -     priv->rpmb_mmc = NULL;
> > +     priv->rpmb_inited = false;
> > +}
> > +
> > +static int check_mmc(struct mmc *mmc)
> > +{
> > +     if (!mmc) {
> > +             debug("Cannot find RPMB device\n");
> > +             return -ENODEV;
> > +     }
> > +     if (!(mmc->version & MMC_VERSION_MMC)) {
> > +             debug("Device id is not an eMMC device\n");
> > +             return -ENODEV;
> > +     }
> > +     if (mmc->version < MMC_VERSION_4_41) {
> > +             debug("RPMB is not supported before version 4.41\n");
> > +             return -ENODEV;
> > +     }
> > +
> > +     return 0;
> >  }
> >
> >  static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
> >  {
> > -     struct mmc *mmc;
> >       int rc;
> >
> > -     if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
> > +     if (priv->rpmb_mmc && priv->rpmb_inited)
> >               return priv->rpmb_mmc;
> >
> >       release_mmc(priv);
> >
> > -     mmc = find_mmc_device(dev_id);
> > -     if (!mmc) {
> > -             debug("Cannot find RPMB device\n");
> > -             return NULL;
> > -     }
> > -     if (!(mmc->version & MMC_VERSION_MMC)) {
> > -             debug("Device id %d is not an eMMC device\n", dev_id);
> > -             return NULL;
> > -     }
> > -     if (mmc->version < MMC_VERSION_4_41) {
> > -             debug("Device id %d: RPMB not supported before version 4.41\n",
> > -                   dev_id);
> > +     /*
> > +      * Check if priv->rpmb_mmc was already set from DT node,
> > +      * otherwise use dev_id provided by OP-TEE OS
> > +      * and find mmc device by its dev_id
> > +      */
> > +     if (!priv->rpmb_mmc)
> > +             priv->rpmb_mmc = find_mmc_device(dev_id);
> > +
> > +     rc = check_mmc(priv->rpmb_mmc);
> > +     if (rc)
> >               return NULL;
> > -     }
> >
> > -     priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
> > +     priv->rpmb_original_part = mmc_get_blk_desc(priv->rpmb_mmc)->hwpart;
> >
> > -     rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
> > +     rc = mmc_switch_part(priv->rpmb_mmc, MMC_PART_RPMB);
> >       if (rc) {
> >               debug("Device id %d: cannot select RPMB partition: %d\n",
> >                     dev_id, rc);
> >               return NULL;
> >       }
> >
> > -     priv->rpmb_mmc = mmc;
> > -     priv->rpmb_dev_id = dev_id;
> > -     return mmc;
> > +     priv->rpmb_inited = true;
> > +     return priv->rpmb_mmc;
> >  }
> >
> >  static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
> > --
> > 2.25.1
> >
Jens Wiklander Jan. 25, 2021, 12:20 p.m. UTC | #3
On Mon, Jan 25, 2021 at 12:50 PM Igor Opaniuk <igor.opaniuk@foundries.io> wrote:
>
> Hi Jens,
>
> On Mon, Jan 25, 2021 at 10:50 AM Jens Wiklander
> <jens.wiklander@linaro.org> wrote:
> >
> > Hi Igor,
> >
> > On Sun, Jan 24, 2021 at 11:39:45AM +0200, Igor Opaniuk wrote:
> > > From: Igor Opaniuk <igor.opaniuk@foundries.io>
> > >
> > > Add support for rpmb-dev property in optee node.
> > > Prioritize that provided eMMC info from DT for RPMB operations over
> > > the one provided by OP-TEE OS core in RPC calls.
> > >
> > > Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
> > > ---
> > >
> > > Changes in v2:
> > > - Return NULL instead of ERR_PTR(-ENXIO) in get_rpmb_dev in case there
> > >   is no rpmb-dev property or somemithing went wrong
> > >
> > >  drivers/tee/optee/core.c          | 33 +++++++++++++++++
> > >  drivers/tee/optee/optee_private.h |  2 +-
> > >  drivers/tee/optee/rpmb.c          | 60 ++++++++++++++++++-------------
> > >  3 files changed, 70 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> > > index b898c32edc..828ab9b00a 100644
> > > --- a/drivers/tee/optee/core.c
> > > +++ b/drivers/tee/optee/core.c
> > > @@ -12,6 +12,7 @@
> > >  #include <linux/arm-smccc.h>
> > >  #include <linux/err.h>
> > >  #include <linux/io.h>
> > > +#include <mmc.h>
> > >
> > >  #include "optee_smc.h"
> > >  #include "optee_msg.h"
> > > @@ -607,14 +608,46 @@ static optee_invoke_fn *get_invoke_func(struct udevice *dev)
> > >       return ERR_PTR(-EINVAL);
> > >  }
> > >
> > > +static struct mmc *get_rpmb_dev(struct udevice *dev)
> > > +{
> > > +     struct udevice *mmc_dev;
> > > +     const fdt32_t *phandle_p;
> > > +     u32 phandle;
> > > +     int ret = 0;
> > > +
> > > +     debug("optee: looking for rpmb device in DT.\n");
> > > +
> > > +     phandle_p  = ofnode_get_property(dev_ofnode(dev),
> > > +                                      "rpmb-dev", NULL);
> > > +     if (!phandle_p) {
> > > +             debug("optee: missing \"rpmb-dev\" property\n");
> >
> > With this we'll complain in the log each time "rpmb-dev" isn't found
> > even when OP-TEE isn't configured to use RPMB. This might cause some
> > confusion.
>
> Sure I'll wrap with "if (IS_ENABLED(CONFIG_SUPPORT_EMMC_RPMB))"
> get_rpmb_dev() invocation in optee_of_to_plat() .
>
> But as it's just a debug message, I would prefer to keep it for
> debugging purposes
> (I can adjust it, adding the phrase that the driver will use OP-TEE
> provided dev id instead).

Sounds good.

Cheers,
Jens
Patrick DELAUNAY Feb. 8, 2021, 3:06 p.m. UTC | #4
Hi Igor,

On 1/24/21 10:39 AM, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@foundries.io>
>
> Add support for rpmb-dev property in optee node.
> Prioritize that provided eMMC info from DT for RPMB operations over
> the one provided by OP-TEE OS core in RPC calls.
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
> ---
>
> Changes in v2:
> - Return NULL instead of ERR_PTR(-ENXIO) in get_rpmb_dev in case there
>    is no rpmb-dev property or somemithing went wrong
>
>   drivers/tee/optee/core.c          | 33 +++++++++++++++++
>   drivers/tee/optee/optee_private.h |  2 +-
>   drivers/tee/optee/rpmb.c          | 60 ++++++++++++++++++-------------
>   3 files changed, 70 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> index b898c32edc..828ab9b00a 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -12,6 +12,7 @@
>   #include <linux/arm-smccc.h>
>   #include <linux/err.h>
>   #include <linux/io.h>
> +#include <mmc.h>
>   
>   #include "optee_smc.h"
>   #include "optee_msg.h"
> @@ -607,14 +608,46 @@ static optee_invoke_fn *get_invoke_func(struct udevice *dev)
>   	return ERR_PTR(-EINVAL);
>   }
>   
> +static struct mmc *get_rpmb_dev(struct udevice *dev)
> +{
> +	struct udevice *mmc_dev;
> +	const fdt32_t *phandle_p;
> +	u32 phandle;
> +	int ret = 0;
> +
> +	debug("optee: looking for rpmb device in DT.\n");
> +
> +	phandle_p  = ofnode_get_property(dev_ofnode(dev),
> +					 "rpmb-dev", NULL);
> +	if (!phandle_p) {
> +		debug("optee: missing \"rpmb-dev\" property\n");
> +		return NULL;
> +	}
> +
> +	phandle = fdt32_to_cpu(*phandle_p);
> +
> +	ret = uclass_get_device_by_phandle_id(UCLASS_MMC, phandle, &mmc_dev);
> +	if (ret) {
> +		printf("optee: invalid phandle value in \"rpmb-dev\".\n");
> +		return NULL;
> +	}
> +
> +	debug("optee: using phandle %d from \"rpmd-dev\" property.\n",
> +	      phandle);
> +	return mmc_get_mmc_dev(mmc_dev);
> +}
> +
>   static int optee_of_to_plat(struct udevice *dev)
>   {
>   	struct optee_pdata *pdata = dev_get_plat(dev);
> +	struct optee_private *priv = dev_get_priv(dev);
>   
>   	pdata->invoke_fn = get_invoke_func(dev);
>   	if (IS_ERR(pdata->invoke_fn))
>   		return PTR_ERR(pdata->invoke_fn);
>   

Normally optee_of_to_plat should initialized only the platdata and not the private date
(initialized during probe or driver execution)

And no need to initialize rpmb_mmcif CONFIG_CMD_OPTEE_RPMBI is not activated,

I proposed:

struct optee_pdata {
     optee_invoke_fn *invoke_fn;
     struct mmc *rpmb_mmc;
};

+ if (IS_ENABLED(CONFIG_CMD_OPTEE_RPMBI))

+    pdata->rpmb_mmc = get_rpmb_dev(dev);

> +	priv->rpmb_mmc = get_rpmb_dev(dev);
> +
>   	return 0;
>   }
>   
> diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> index 1f07a27ee4..8e5a280622 100644
> --- a/drivers/tee/optee/optee_private.h
> +++ b/drivers/tee/optee/optee_private.h
> @@ -19,8 +19,8 @@
>    */
>   struct optee_private {
>   	struct mmc *rpmb_mmc;
> -	int rpmb_dev_id;
>   	int rpmb_original_part;
> +	bool rpmb_inited;
>   };
>   
>   struct optee_msg_arg;
> diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
> index 0804fc963c..0137c44be1 100644
> --- a/drivers/tee/optee/rpmb.c
> +++ b/drivers/tee/optee/rpmb.c
> @@ -45,55 +45,67 @@ static void release_mmc(struct optee_private *priv)
>   {
>   	int rc;
>   
> -	if (!priv->rpmb_mmc)
> +	if (!priv->rpmb_mmc || !priv->rpmb_inited)
>   		return;
>   
> -	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
> -				      priv->rpmb_original_part);
> +	rc = mmc_switch_part(priv->rpmb_mmc, priv->rpmb_original_part);
>   	if (rc)
>   		debug("%s: blk_select_hwpart_devnum() failed: %d\n",
>   		      __func__, rc);
>   
> -	priv->rpmb_mmc = NULL;
> +	priv->rpmb_inited = false;
> +}
> +
> +static int check_mmc(struct mmc *mmc)
> +{
> +	if (!mmc) {
> +		debug("Cannot find RPMB device\n");
> +		return -ENODEV;
> +	}
> +	if (!(mmc->version & MMC_VERSION_MMC)) {
> +		debug("Device id is not an eMMC device\n");
> +		return -ENODEV;
> +	}
> +	if (mmc->version < MMC_VERSION_4_41) {
> +		debug("RPMB is not supported before version 4.41\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
>   }
>   
>   static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
>   {
> -	struct mmc *mmc;
>   	int rc;
>   
> -	if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
> +	if (priv->rpmb_mmc && priv->rpmb_inited)
>   		return priv->rpmb_mmc;
>   
>   	release_mmc(priv);

really need to release mmc here (it is not initialized) as the first test of

the called function is:

     if (!priv->rpmb_mmc || !priv->rpmb_inited)


>   
> -	mmc = find_mmc_device(dev_id);
> -	if (!mmc) {
> -		debug("Cannot find RPMB device\n");
> -		return NULL;
> -	}
> -	if (!(mmc->version & MMC_VERSION_MMC)) {
> -		debug("Device id %d is not an eMMC device\n", dev_id);
> -		return NULL;
> -	}
> -	if (mmc->version < MMC_VERSION_4_41) {
> -		debug("Device id %d: RPMB not supported before version 4.41\n",
> -		      dev_id);
> +	/*
> +	 * Check if priv->rpmb_mmc was already set from DT node,
> +	 * otherwise use dev_id provided by OP-TEE OS
> +	 * and find mmc device by its dev_id
> +	 */
> +	if (!priv->rpmb_mmc)
> +		priv->rpmb_mmc = find_mmc_device(dev_id);



if (plat->rpmb_mmc)

	priv->rpmb_mmc = plat->rpmb_mmc
else
	priv->rpmb_mmc = find_mmc_device(dev_id);


and priv->rpmb_inited is nore more required (if priv->rpmb_mmc = NULL; on each error)

> +
> +	rc = check_mmc(priv->rpmb_mmc);
> +	if (rc)
>   		return NULL;
> -	}
>   
> -	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
> +	priv->rpmb_original_part = mmc_get_blk_desc(priv->rpmb_mmc)->hwpart;
>   
> -	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
> +	rc = mmc_switch_part(priv->rpmb_mmc, MMC_PART_RPMB);
>   	if (rc) {
>   		debug("Device id %d: cannot select RPMB partition: %d\n",
>   		      dev_id, rc);
>   		return NULL;
>   	}
>   
> -	priv->rpmb_mmc = mmc;
> -	priv->rpmb_dev_id = dev_id;
> -	return mmc;
> +	priv->rpmb_inited = true;
> +	return priv->rpmb_mmc;
>   }
>   
>   static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)


regards


Patrick
Igor Opaniuk Feb. 8, 2021, 11:33 p.m. UTC | #5
Hi Patrick,

On Mon, Feb 8, 2021 at 5:06 PM Patrick DELAUNAY
<patrick.delaunay@foss.st.com> wrote:
>
> Hi Igor,
>
> On 1/24/21 10:39 AM, Igor Opaniuk wrote:
> > From: Igor Opaniuk <igor.opaniuk@foundries.io>
> >
> > Add support for rpmb-dev property in optee node.
> > Prioritize that provided eMMC info from DT for RPMB operations over
> > the one provided by OP-TEE OS core in RPC calls.
> >
> > Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
> > ---
> >
> > Changes in v2:
> > - Return NULL instead of ERR_PTR(-ENXIO) in get_rpmb_dev in case there
> >    is no rpmb-dev property or somemithing went wrong
> >
> >   drivers/tee/optee/core.c          | 33 +++++++++++++++++
> >   drivers/tee/optee/optee_private.h |  2 +-
> >   drivers/tee/optee/rpmb.c          | 60 ++++++++++++++++++-------------
> >   3 files changed, 70 insertions(+), 25 deletions(-)
> >
> > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
> > index b898c32edc..828ab9b00a 100644
> > --- a/drivers/tee/optee/core.c
> > +++ b/drivers/tee/optee/core.c
> > @@ -12,6 +12,7 @@
> >   #include <linux/arm-smccc.h>
> >   #include <linux/err.h>
> >   #include <linux/io.h>
> > +#include <mmc.h>
> >
> >   #include "optee_smc.h"
> >   #include "optee_msg.h"
> > @@ -607,14 +608,46 @@ static optee_invoke_fn *get_invoke_func(struct udevice *dev)
> >       return ERR_PTR(-EINVAL);
> >   }
> >
> > +static struct mmc *get_rpmb_dev(struct udevice *dev)
> > +{
> > +     struct udevice *mmc_dev;
> > +     const fdt32_t *phandle_p;
> > +     u32 phandle;
> > +     int ret = 0;
> > +
> > +     debug("optee: looking for rpmb device in DT.\n");
> > +
> > +     phandle_p  = ofnode_get_property(dev_ofnode(dev),
> > +                                      "rpmb-dev", NULL);
> > +     if (!phandle_p) {
> > +             debug("optee: missing \"rpmb-dev\" property\n");
> > +             return NULL;
> > +     }
> > +
> > +     phandle = fdt32_to_cpu(*phandle_p);
> > +
> > +     ret = uclass_get_device_by_phandle_id(UCLASS_MMC, phandle, &mmc_dev);
> > +     if (ret) {
> > +             printf("optee: invalid phandle value in \"rpmb-dev\".\n");
> > +             return NULL;
> > +     }
> > +
> > +     debug("optee: using phandle %d from \"rpmd-dev\" property.\n",
> > +           phandle);
> > +     return mmc_get_mmc_dev(mmc_dev);
> > +}
> > +
> >   static int optee_of_to_plat(struct udevice *dev)
> >   {
> >       struct optee_pdata *pdata = dev_get_plat(dev);
> > +     struct optee_private *priv = dev_get_priv(dev);
> >
> >       pdata->invoke_fn = get_invoke_func(dev);
> >       if (IS_ERR(pdata->invoke_fn))
> >               return PTR_ERR(pdata->invoke_fn);
> >
>
> Normally optee_of_to_plat should initialized only the platdata and not the private date
> (initialized during probe or driver execution)

To be honest that was my initial intention to do that way,
but that would have required a complete overhaul of all functions in
optee/rpmb.c,
so I just tried to find a "golden mean" between the approach you described
and something less intrusive.

>
> And no need to initialize rpmb_mmcif CONFIG_CMD_OPTEE_RPMBI is not activated,
Yeah, will fix that.

>
> I proposed:
>
> struct optee_pdata {
>      optee_invoke_fn *invoke_fn;
>      struct mmc *rpmb_mmc;
> };
>
> + if (IS_ENABLED(CONFIG_CMD_OPTEE_RPMBI))
>
> +    pdata->rpmb_mmc = get_rpmb_dev(dev);
>
> > +     priv->rpmb_mmc = get_rpmb_dev(dev);
> > +
> >       return 0;
> >   }
> >
> > diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
> > index 1f07a27ee4..8e5a280622 100644
> > --- a/drivers/tee/optee/optee_private.h
> > +++ b/drivers/tee/optee/optee_private.h
> > @@ -19,8 +19,8 @@
> >    */
> >   struct optee_private {
> >       struct mmc *rpmb_mmc;
> > -     int rpmb_dev_id;
> >       int rpmb_original_part;
> > +     bool rpmb_inited;
> >   };
> >
> >   struct optee_msg_arg;
> > diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
> > index 0804fc963c..0137c44be1 100644
> > --- a/drivers/tee/optee/rpmb.c
> > +++ b/drivers/tee/optee/rpmb.c
> > @@ -45,55 +45,67 @@ static void release_mmc(struct optee_private *priv)
> >   {
> >       int rc;
> >
> > -     if (!priv->rpmb_mmc)
> > +     if (!priv->rpmb_mmc || !priv->rpmb_inited)
> >               return;
> >
> > -     rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
> > -                                   priv->rpmb_original_part);
> > +     rc = mmc_switch_part(priv->rpmb_mmc, priv->rpmb_original_part);
> >       if (rc)
> >               debug("%s: blk_select_hwpart_devnum() failed: %d\n",
> >                     __func__, rc);
> >
> > -     priv->rpmb_mmc = NULL;
> > +     priv->rpmb_inited = false;
> > +}
> > +
> > +static int check_mmc(struct mmc *mmc)
> > +{
> > +     if (!mmc) {
> > +             debug("Cannot find RPMB device\n");
> > +             return -ENODEV;
> > +     }
> > +     if (!(mmc->version & MMC_VERSION_MMC)) {
> > +             debug("Device id is not an eMMC device\n");
> > +             return -ENODEV;
> > +     }
> > +     if (mmc->version < MMC_VERSION_4_41) {
> > +             debug("RPMB is not supported before version 4.41\n");
> > +             return -ENODEV;
> > +     }
> > +
> > +     return 0;
> >   }
> >
> >   static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
> >   {
> > -     struct mmc *mmc;
> >       int rc;
> >
> > -     if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
> > +     if (priv->rpmb_mmc && priv->rpmb_inited)
> >               return priv->rpmb_mmc;
> >
> >       release_mmc(priv);
>
> really need to release mmc here (it is not initialized) as the first test of
>
> the called function is:
>
>      if (!priv->rpmb_mmc || !priv->rpmb_inited)
>
>
> >
> > -     mmc = find_mmc_device(dev_id);
> > -     if (!mmc) {
> > -             debug("Cannot find RPMB device\n");
> > -             return NULL;
> > -     }
> > -     if (!(mmc->version & MMC_VERSION_MMC)) {
> > -             debug("Device id %d is not an eMMC device\n", dev_id);
> > -             return NULL;
> > -     }
> > -     if (mmc->version < MMC_VERSION_4_41) {
> > -             debug("Device id %d: RPMB not supported before version 4.41\n",
> > -                   dev_id);
> > +     /*
> > +      * Check if priv->rpmb_mmc was already set from DT node,
> > +      * otherwise use dev_id provided by OP-TEE OS
> > +      * and find mmc device by its dev_id
> > +      */
> > +     if (!priv->rpmb_mmc)
> > +             priv->rpmb_mmc = find_mmc_device(dev_id);
>
>
>
> if (plat->rpmb_mmc)
>
>         priv->rpmb_mmc = plat->rpmb_mmc
> else
>         priv->rpmb_mmc = find_mmc_device(dev_id);
>
>
> and priv->rpmb_inited is nore more required (if priv->rpmb_mmc = NULL; on each error)
>
> > +
> > +     rc = check_mmc(priv->rpmb_mmc);
> > +     if (rc)
> >               return NULL;
> > -     }
> >
> > -     priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
> > +     priv->rpmb_original_part = mmc_get_blk_desc(priv->rpmb_mmc)->hwpart;
> >
> > -     rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
> > +     rc = mmc_switch_part(priv->rpmb_mmc, MMC_PART_RPMB);
> >       if (rc) {
> >               debug("Device id %d: cannot select RPMB partition: %d\n",
> >                     dev_id, rc);
> >               return NULL;
> >       }
> >
> > -     priv->rpmb_mmc = mmc;
> > -     priv->rpmb_dev_id = dev_id;
> > -     return mmc;
> > +     priv->rpmb_inited = true;
> > +     return priv->rpmb_mmc;
> >   }
> >
> >   static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)
>
>
> regards
>
>
> Patrick
>

The principal problem here is a new "rpmb-dev" property for optee DT
node which I introduced
in this patch set. As in Linux all RPMB RPC calls are handled by tee
supplicant running
in user space, unlikely I can somehow justify why we need that
additional property
if it is not going to be used by optee linux kernel driver.

We can still have a temporary approach with u-boot-specific property
(something like `u-boot,rpmb-dev` in u-boot specific dtsi),  but that will
create additional fragmentation and divergence between U-Boot/Linux,
which I want to avoid. So I'm still thinking about what could be a
better solution here.

For additional details please check [1]

[1] https://github.com/OP-TEE/optee_os/issues/4343
diff mbox series

Patch

diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index b898c32edc..828ab9b00a 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -12,6 +12,7 @@ 
 #include <linux/arm-smccc.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <mmc.h>
 
 #include "optee_smc.h"
 #include "optee_msg.h"
@@ -607,14 +608,46 @@  static optee_invoke_fn *get_invoke_func(struct udevice *dev)
 	return ERR_PTR(-EINVAL);
 }
 
+static struct mmc *get_rpmb_dev(struct udevice *dev)
+{
+	struct udevice *mmc_dev;
+	const fdt32_t *phandle_p;
+	u32 phandle;
+	int ret = 0;
+
+	debug("optee: looking for rpmb device in DT.\n");
+
+	phandle_p  = ofnode_get_property(dev_ofnode(dev),
+					 "rpmb-dev", NULL);
+	if (!phandle_p) {
+		debug("optee: missing \"rpmb-dev\" property\n");
+		return NULL;
+	}
+
+	phandle = fdt32_to_cpu(*phandle_p);
+
+	ret = uclass_get_device_by_phandle_id(UCLASS_MMC, phandle, &mmc_dev);
+	if (ret) {
+		printf("optee: invalid phandle value in \"rpmb-dev\".\n");
+		return NULL;
+	}
+
+	debug("optee: using phandle %d from \"rpmd-dev\" property.\n",
+	      phandle);
+	return mmc_get_mmc_dev(mmc_dev);
+}
+
 static int optee_of_to_plat(struct udevice *dev)
 {
 	struct optee_pdata *pdata = dev_get_plat(dev);
+	struct optee_private *priv = dev_get_priv(dev);
 
 	pdata->invoke_fn = get_invoke_func(dev);
 	if (IS_ERR(pdata->invoke_fn))
 		return PTR_ERR(pdata->invoke_fn);
 
+	priv->rpmb_mmc = get_rpmb_dev(dev);
+
 	return 0;
 }
 
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 1f07a27ee4..8e5a280622 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -19,8 +19,8 @@ 
  */
 struct optee_private {
 	struct mmc *rpmb_mmc;
-	int rpmb_dev_id;
 	int rpmb_original_part;
+	bool rpmb_inited;
 };
 
 struct optee_msg_arg;
diff --git a/drivers/tee/optee/rpmb.c b/drivers/tee/optee/rpmb.c
index 0804fc963c..0137c44be1 100644
--- a/drivers/tee/optee/rpmb.c
+++ b/drivers/tee/optee/rpmb.c
@@ -45,55 +45,67 @@  static void release_mmc(struct optee_private *priv)
 {
 	int rc;
 
-	if (!priv->rpmb_mmc)
+	if (!priv->rpmb_mmc || !priv->rpmb_inited)
 		return;
 
-	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, priv->rpmb_dev_id,
-				      priv->rpmb_original_part);
+	rc = mmc_switch_part(priv->rpmb_mmc, priv->rpmb_original_part);
 	if (rc)
 		debug("%s: blk_select_hwpart_devnum() failed: %d\n",
 		      __func__, rc);
 
-	priv->rpmb_mmc = NULL;
+	priv->rpmb_inited = false;
+}
+
+static int check_mmc(struct mmc *mmc)
+{
+	if (!mmc) {
+		debug("Cannot find RPMB device\n");
+		return -ENODEV;
+	}
+	if (!(mmc->version & MMC_VERSION_MMC)) {
+		debug("Device id is not an eMMC device\n");
+		return -ENODEV;
+	}
+	if (mmc->version < MMC_VERSION_4_41) {
+		debug("RPMB is not supported before version 4.41\n");
+		return -ENODEV;
+	}
+
+	return 0;
 }
 
 static struct mmc *get_mmc(struct optee_private *priv, int dev_id)
 {
-	struct mmc *mmc;
 	int rc;
 
-	if (priv->rpmb_mmc && priv->rpmb_dev_id == dev_id)
+	if (priv->rpmb_mmc && priv->rpmb_inited)
 		return priv->rpmb_mmc;
 
 	release_mmc(priv);
 
-	mmc = find_mmc_device(dev_id);
-	if (!mmc) {
-		debug("Cannot find RPMB device\n");
-		return NULL;
-	}
-	if (!(mmc->version & MMC_VERSION_MMC)) {
-		debug("Device id %d is not an eMMC device\n", dev_id);
-		return NULL;
-	}
-	if (mmc->version < MMC_VERSION_4_41) {
-		debug("Device id %d: RPMB not supported before version 4.41\n",
-		      dev_id);
+	/*
+	 * Check if priv->rpmb_mmc was already set from DT node,
+	 * otherwise use dev_id provided by OP-TEE OS
+	 * and find mmc device by its dev_id
+	 */
+	if (!priv->rpmb_mmc)
+		priv->rpmb_mmc = find_mmc_device(dev_id);
+
+	rc = check_mmc(priv->rpmb_mmc);
+	if (rc)
 		return NULL;
-	}
 
-	priv->rpmb_original_part = mmc_get_blk_desc(mmc)->hwpart;
+	priv->rpmb_original_part = mmc_get_blk_desc(priv->rpmb_mmc)->hwpart;
 
-	rc = blk_select_hwpart_devnum(IF_TYPE_MMC, dev_id, MMC_PART_RPMB);
+	rc = mmc_switch_part(priv->rpmb_mmc, MMC_PART_RPMB);
 	if (rc) {
 		debug("Device id %d: cannot select RPMB partition: %d\n",
 		      dev_id, rc);
 		return NULL;
 	}
 
-	priv->rpmb_mmc = mmc;
-	priv->rpmb_dev_id = dev_id;
-	return mmc;
+	priv->rpmb_inited = true;
+	return priv->rpmb_mmc;
 }
 
 static u32 rpmb_get_dev_info(u16 dev_id, struct rpmb_dev_info *info)