Re: [PATCHv4 2/5] fwu: move meta-data management in core
Hello Jassi, On Sun, 5 Feb 2023 at 04:01, wrote: > > From: Jassi Brar > > Instead of each i/f having to implement their own meta-data verification > and storage, move the logic in common code. This simplifies the i/f code > much simpler and compact. > > Signed-off-by: Jassi Brar > --- > drivers/fwu-mdata/fwu-mdata-uclass.c | 34 +++ > include/fwu.h| 41 > lib/fwu_updates/fwu.c| 135 ++- > 3 files changed, 206 insertions(+), 4 deletions(-) > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > b/drivers/fwu-mdata/fwu-mdata-uclass.c > index b477e9603f..e03773c584 100644 > --- a/drivers/fwu-mdata/fwu-mdata-uclass.c > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > @@ -16,6 +16,40 @@ > #include > #include > > +/** > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > + * > + * Return: 0 if OK, -ve on error > + */ > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->read_mdata) { > + log_debug("read_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->read_mdata(dev, mdata, primary); > +} > + > +/** > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > + * > + * Return: 0 if OK, -ve on error > + */ > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->write_mdata) { > + log_debug("write_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->write_mdata(dev, mdata, primary); > +} > + > /** > * fwu_get_mdata_part_num() - Get the FWU metadata partition numbers > * @dev: FWU metadata device > diff --git a/include/fwu.h b/include/fwu.h > index 0919ced812..1a700c9e6a 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -24,6 +24,26 @@ struct fwu_mdata_gpt_blk_priv { > * @update_mdata() - Update the FWU metadata copy > */ > struct fwu_mdata_ops { > + /** > +* read_mdata() - Populate the asked FWU metadata copy > +* @dev: FWU metadata device > +* @mdata: Copy of the FWU metadata > +* @primary: If primary or secondary copy of meta-data is to be read > +* > +* Return: 0 if OK, -ve on error > +*/ > + int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > + /** > +* write_mdata() - Write the given FWU metadata copy > +* @dev: FWU metadata device > +* @mdata: Copy of the FWU metadata > +* @primary: If primary or secondary copy of meta-data is to be > written > +* > +* Return: 0 if OK, -ve on error > +*/ > + int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > /** > * check_mdata() - Check if the FWU metadata is valid > * @dev:FWU device > @@ -126,6 +146,27 @@ struct fwu_mdata_ops { > EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ > 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) > > +/** > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > + */ > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > +/** > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > + */ > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > +/** > + * fwu_get_verified_mdata() - Read, verify and return the FWU metadata > + * > + * Read both the metadata copies from the storage media, verify their > checksum, > + * and ascertain that both copies match. If one of the copies has gone bad, > + * restore it from the good copy. > + * > + * Return: 0 if OK, -ve on error > +*/ > +int fwu_get_verified_mdata(struct fwu_mdata *mdata); > + > /** > * fwu_check_mdata_validity() - Check for validity of the FWU metadata copies > * > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 5313d07302..56299f1b2f 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -15,13 +15,13 @@ > #include > #include > > +#include > + > +static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid > */ > +static struct udevice *g_dev; > static u8 in_trial; > static u8 boottime_check; > > -#include > -#include > -#include > - > enum { > IMAGE_ACCEPT_SET = 1, > IMAGE_ACCEPT_CLEAR, > @@ -161,6 +161,133 @@ static int fwu_get_image_type_id(u8 *image_index, > efi_guid_t *image_type_id) > return -ENOENT; > } > > +/** > + * fwu_sync_mdata() - Update given meta-data partition(s) with the copy > provided > + * @mdata: FWU metadata structure > + * @part: Bitmask of FWU metadata partitions to be written to > + * > + * Return: 0 if OK, -ve on erro
Re: [PATCHv4 2/5] fwu: move meta-data management in core
- err = fwu_write_mdata(g_dev, mdata, part & PRIMARY_PART ? true : false); On Mon, 27 Feb 2023 at 17:46, Jassi Brar wrote: > > On Mon, Feb 27, 2023 at 10:30 AM Etienne Carriere > wrote: > > > > Hello Jassi, > > > > On Sun, 5 Feb 2023 at 04:01, wrote: > > > > > > From: Jassi Brar > > > > > > Instead of each i/f having to implement their own meta-data verification > > > and storage, move the logic in common code. This simplifies the i/f code > > > much simpler and compact. > > > > > > Signed-off-by: Jassi Brar > > > --- > > > drivers/fwu-mdata/fwu-mdata-uclass.c | 34 +++ > > > include/fwu.h| 41 > > > lib/fwu_updates/fwu.c| 135 ++- > > > 3 files changed, 206 insertions(+), 4 deletions(-) > > > > > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > > > b/drivers/fwu-mdata/fwu-mdata-uclass.c > > > index b477e9603f..e03773c584 100644 > > > --- a/drivers/fwu-mdata/fwu-mdata-uclass.c > > > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > > > @@ -16,6 +16,40 @@ > > > #include > > > #include > > > > > > +/** > > > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > > > + * > > > + * Return: 0 if OK, -ve on error > > > + */ > > > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > > > primary) > > > +{ > > > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > > > + > > > + if (!ops->read_mdata) { > > > + log_debug("read_mdata() method not defined\n"); > > > + return -ENOSYS; > > > + } > > > + > > > + return ops->read_mdata(dev, mdata, primary); > > > +} > > > + > > > +/** > > > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > > > + * > > > + * Return: 0 if OK, -ve on error > > > + */ > > > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > > > primary) > > > +{ > > > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > > > + > > > + if (!ops->write_mdata) { > > > + log_debug("write_mdata() method not defined\n"); > > > + return -ENOSYS; > > > + } > > > + > > > + return ops->write_mdata(dev, mdata, primary); > > > +} > > > + > > > /** > > > * fwu_get_mdata_part_num() - Get the FWU metadata partition numbers > > > * @dev: FWU metadata device > > > diff --git a/include/fwu.h b/include/fwu.h > > > index 0919ced812..1a700c9e6a 100644 > > > --- a/include/fwu.h > > > +++ b/include/fwu.h > > > @@ -24,6 +24,26 @@ struct fwu_mdata_gpt_blk_priv { > > > * @update_mdata() - Update the FWU metadata copy > > > */ > > > struct fwu_mdata_ops { > > > + /** > > > +* read_mdata() - Populate the asked FWU metadata copy > > > +* @dev: FWU metadata device > > > +* @mdata: Copy of the FWU metadata > > > +* @primary: If primary or secondary copy of meta-data is to be > > > read > > > +* > > > +* Return: 0 if OK, -ve on error > > > +*/ > > > + int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, > > > bool primary); > > > + > > > + /** > > > +* write_mdata() - Write the given FWU metadata copy > > > +* @dev: FWU metadata device > > > +* @mdata: Copy of the FWU metadata > > > +* @primary: If primary or secondary copy of meta-data is to be > > > written > > > +* > > > +* Return: 0 if OK, -ve on error > > > +*/ > > > + int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, > > > bool primary); > > > + > > > /** > > > * check_mdata() - Check if the FWU metadata is valid > > > * @dev:FWU device > > > @@ -126,6 +146,27 @@ struct fwu_mdata_ops { > > > EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ > > > 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) > > > > > > +/** > > > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > > > + */
Re: [PATCH v5 4/6] fwu: gpt: implement read_mdata and write_mdata callbacks
On Tue, 28 Feb 2023 at 01:52, wrote: > > From: Jassi Brar > > Moving towards using common code for meta-data management, > implement the read/write mdata hooks. > > Signed-off-by: Jassi Brar > Reviewed-by: Etienne Carriere > Reviewed-by: Ilias Apalodimas > --- > drivers/fwu-mdata/gpt_blk.c | 36 > 1 file changed, 36 insertions(+) > > diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c > index 28f5d23e1e..bdaa10cd1d 100644 > --- a/drivers/fwu-mdata/gpt_blk.c > +++ b/drivers/fwu-mdata/gpt_blk.c > @@ -272,7 +272,43 @@ static int fwu_mdata_gpt_blk_probe(struct udevice *dev) > return 0; > } > > +static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, > +bool primary) > +{ > + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > + struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); > + int ret; > + > + ret = gpt_get_mdata_partitions(desc); > + if (ret < 0) { > + log_debug("Error getting the FWU metadata partitions\n"); > + return -ENOENT; > + } > + > + return gpt_read_write_mdata(desc, mdata, MDATA_READ, > +primary ? g_mdata_part[0] : g_mdata_part[1]); Indentation to fix. > +} > + > +static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, > +bool primary) > +{ > + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > + struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); > + int ret; > + > + ret = gpt_get_mdata_partitions(desc); > + if (ret < 0) { > + log_debug("Error getting the FWU metadata partitions\n"); > + return -ENOENT; > + } > + > + return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, > +primary ? g_mdata_part[0] : g_mdata_part[1]); Indentation to fix. With these 2 comments addressed, my R-B tag applies. > +} > + > static const struct fwu_mdata_ops fwu_gpt_blk_ops = { > + .read_mdata = fwu_gpt_read_mdata, > + .write_mdata = fwu_gpt_write_mdata, > .get_mdata = fwu_gpt_get_mdata, > .update_mdata = fwu_gpt_update_mdata, > .get_mdata_part_num = fwu_gpt_get_mdata_partitions, > -- > 2.34.1 >
Re: [PATCH v5 3/6] fwu: move meta-data management in core
Hello Jassi, On Tue, 28 Feb 2023 at 01:52, wrote: > > From: Jassi Brar > > Instead of each i/f having to implement their own meta-data verification > and storage, move the logic in common code. This simplifies the i/f code > much simpler and compact. > > Signed-off-by: Jassi Brar > --- > drivers/fwu-mdata/fwu-mdata-uclass.c | 34 +++ > include/fwu.h| 41 + > lib/fwu_updates/fwu.c| 130 +-- > 3 files changed, 200 insertions(+), 5 deletions(-) > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > b/drivers/fwu-mdata/fwu-mdata-uclass.c > index b477e9603f..e03773c584 100644 > --- a/drivers/fwu-mdata/fwu-mdata-uclass.c > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > @@ -16,6 +16,40 @@ > #include > #include > > +/** > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > + * > + * Return: 0 if OK, -ve on error > + */ Inline description only in header file, or duplicated in source and header files? > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->read_mdata) { > + log_debug("read_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->read_mdata(dev, mdata, primary); > +} > + > +/** > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > + * > + * Return: 0 if OK, -ve on error > + */ > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->write_mdata) { > + log_debug("write_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->write_mdata(dev, mdata, primary); > +} > + > /** > * fwu_get_mdata_part_num() - Get the FWU metadata partition numbers > * @dev: FWU metadata device > diff --git a/include/fwu.h b/include/fwu.h > index 0919ced812..1a700c9e6a 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -24,6 +24,26 @@ struct fwu_mdata_gpt_blk_priv { > * @update_mdata() - Update the FWU metadata copy > */ > struct fwu_mdata_ops { > + /** > +* read_mdata() - Populate the asked FWU metadata copy > +* @dev: FWU metadata device > +* @mdata: Copy of the FWU metadata @mdata: Output FWU mdata read > +* @primary: If primary or secondary copy of meta-data is to be read s/meta-data/FWU metadata/ Ditto in .write_mdata description > +* > +* Return: 0 if OK, -ve on error > +*/ > + int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > + /** > +* write_mdata() - Write the given FWU metadata copy > +* @dev: FWU metadata device > +* @mdata: Copy of the FWU metadata > +* @primary: If primary or secondary copy of meta-data is to be > written > +* > +* Return: 0 if OK, -ve on error > +*/ > + int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > /** > * check_mdata() - Check if the FWU metadata is valid > * @dev:FWU device > @@ -126,6 +146,27 @@ struct fwu_mdata_ops { > EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ > 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) > > +/** > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > + */ > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > +/** > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > + */ > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > +/** > + * fwu_get_verified_mdata() - Read, verify and return the FWU metadata > + * > + * Read both the metadata copies from the storage media, verify their > checksum, > + * and ascertain that both copies match. If one of the copies has gone bad, > + * restore it from the good copy. @mdata: Output FWU metadata read or NULL > + * > + * Return: 0 if OK, -ve on error > +*/ > +int fwu_get_verified_mdata(struct fwu_mdata *mdata); > + > /** > * fwu_check_mdata_validity() - Check for validity of the FWU metadata copies > * > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 5313d07302..7d195964a2 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -15,13 +15,13 @@ > #include > #include > > +#include > + > +static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid > */ > +static struct udevice *g_dev; > static u8 in_trial; > static u8 boottime_check; > > -#include > -#include > -#include > - > enum { > IMAGE_ACCEPT_SET = 1, > IMAGE_ACCEPT_CLEAR, > @@ -161,6 +161,126 @@ static int fwu_get_image_type_id(u8 *image_index, > efi_guid_t *image_type_id) > return -ENOENT; > } > > +/** > + *
Re: [PATCH v3 04/13] firmware: scmi: framework for installing additional protocols
> From: AKASHI Takahiro > Sent: Friday, September 8, 2023 04:51 > > This framework allows SCMI protocols to be installed and bound to the agent > so that the agent can manage and utilize them later. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > Reviewed-by: Etienne Carriere > --- > v3 > * move "per_device_plat_auto" from a earlier patch > * fix comments in "scmi_agent_priv" > * modify an order of include files in scmi_agent.h > v2 > * check for availability of protocols > --- > drivers/firmware/scmi/scmi_agent-uclass.c | 101 +- > include/scmi_agent-uclass.h | 15 +++- > include/scmi_agent.h | 14 +++ > 3 files changed, 126 insertions(+), 4 deletions(-) > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index 94e54eeb066b..e823d105a3eb 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -38,6 +38,86 @@ static const struct error_code scmi_linux_errmap[] = { > { .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, }, > }; > > +/* > + * NOTE: The only one instance should exist according to > + * the current specification and device tree bindings. > + */ > +struct udevice *scmi_agent; > + > +struct udevice *scmi_get_protocol(struct udevice *dev, > + enum scmi_std_protocol id) > +{ > + struct scmi_agent_priv *priv; > + struct udevice *proto; > + > + priv = dev_get_uclass_plat(dev); > + if (!priv) { > + dev_err(dev, "No priv data found\n"); > + return NULL; > + } > + > + switch (id) { > + case SCMI_PROTOCOL_ID_CLOCK: > + proto = priv->clock_dev; > + break; > + case SCMI_PROTOCOL_ID_RESET_DOMAIN: > + proto = priv->resetdom_dev; > + break; > + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > + proto = priv->voltagedom_dev; > + break; > + default: > + dev_err(dev, "Protocol not supported\n"); > + proto = NULL; > + break; > + } > + if (proto && device_probe(proto)) > + dev_err(dev, "Probe failed\n"); > + > + return proto; > +} > + > +/** > + * scmi_add_protocol - add protocol to agent > + * @dev: SCMI agent device > + * @proto_id: SCMI protocol ID > + * @proto: SCMI protocol device > + * > + * Associate the protocol instance, @proto, to the agent, @dev, > + * for later use. > + * > + * Return: 0 on success, error code otherwise > + */ > +static int scmi_add_protocol(struct udevice *dev, > + enum scmi_std_protocol proto_id, > + struct udevice *proto) > +{ > + struct scmi_agent_priv *priv; > + > + priv = dev_get_uclass_plat(dev); > + if (!priv) { > + dev_err(dev, "No priv data found\n"); > + return -ENODEV; > + } > + > + switch (proto_id) { > + case SCMI_PROTOCOL_ID_CLOCK: > + priv->clock_dev = proto; > + break; > + case SCMI_PROTOCOL_ID_RESET_DOMAIN: > + priv->resetdom_dev = proto; > + break; > + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > + priv->voltagedom_dev = proto; > + break; > + default: > + dev_err(dev, "Protocol not supported\n"); > + return -EPROTO; > + } > + > + return 0; > +} > + > int scmi_to_linux_errno(s32 scmi_code) > { > int n; > @@ -164,12 +244,14 @@ int devm_scmi_process_msg(struct udevice *dev, struct > scmi_msg *msg) > */ > static int scmi_bind_protocols(struct udevice *dev) > { > + struct udevice *agent; nit: my build reported 'agent' here is not used in the scope of this patch. Strictly speaking, it should be brought by patch v3 05/13. ("firmware: scmi: install base protocol to SCMI agent") BR, etienne > (snip)
Re: [PATCH v3 01/13] scmi: refactor the code to hide a channel from devices
Hello Akashi-san, > > From: AKASHI Takahiro > Sent: Friday, September 8, 2023 04:51 > > The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel > reference") added an explicit parameter, channel, but it seems to make > the code complex. > > Hiding this parameter will allow for adding a generic (protocol-agnostic) > helper function, i.e. for PROTOCOL_VERSION, in a later patch. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > --- > v3 > * fix an issue on ST board (reported by Etienne) > by taking care of cases where probed devices are children of > SCMI protocol device (i.e. clock devices under CCF) > See find_scmi_protocol_device(). > * move "per_device_plato_auto" to a succeeding right patch > v2 > * new patch > --- > drivers/clk/clk_scmi.c | 27 +--- > drivers/firmware/scmi/scmi_agent-uclass.c | 160 +++--- > drivers/power/regulator/scmi_regulator.c | 27 +--- > drivers/reset/reset-scmi.c | 19 +-- > include/scmi_agent.h | 15 +- > 5 files changed, 103 insertions(+), 145 deletions(-) > > diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c > index d172fed24c9d..34a49363a51a 100644 > --- a/drivers/clk/clk_scmi.c > +++ b/drivers/clk/clk_scmi.c > @@ -13,17 +13,8 @@ > #include > #include > > -/** > - * struct scmi_clk_priv - Private data for SCMI clocks > - * @channel: Reference to the SCMI channel to use > - */ > -struct scmi_clk_priv { > - struct scmi_channel *channel; > -}; > - > static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) > { > - struct scmi_clk_priv *priv = dev_get_priv(dev); > struct scmi_clk_protocol_attr_out out; > struct scmi_msg msg = { > .protocol_id = SCMI_PROTOCOL_ID_CLOCK, > @@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, > size_t *num_clocks) > }; > int ret; > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(dev, &msg); > if (ret) > return ret; > > @@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, > size_t *num_clocks) > > static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) > { > - struct scmi_clk_priv *priv = dev_get_priv(dev); > struct scmi_clk_attribute_in in = { > .clock_id = clkid, > }; > @@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int > clkid, char **name) > }; > int ret; > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(dev, &msg); > if (ret) > return ret; > > @@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int > clkid, char **name) > > static int scmi_clk_gate(struct clk *clk, int enable) > { > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); > struct scmi_clk_state_in in = { > .clock_id = clk->id, > .attributes = enable, > @@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable) > in, out); > int ret; > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(clk->dev, &msg); > if (ret) > return ret; > > @@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk) > > static ulong scmi_clk_get_rate(struct clk *clk) > { > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); > struct scmi_clk_rate_get_in in = { > .clock_id = clk->id, > }; > @@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk) > in, out); > int ret; > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(clk->dev, &msg); > if (ret < 0) > return ret; > > @@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk) > > static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) > { > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); > struct scmi_clk_rate_set_in in = { > .clock_id = clk->id, > .flags = SCMI_CLK_RATE_ROUND_CLOSEST, > @@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong > rate) > in, out); > int ret; > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(clk->dev, &msg); > if (ret < 0) > return ret; > > @@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong > rate) > > static int scmi_clk_probe(struct udevice *dev) > { > - struct scmi_clk_priv *priv = dev_get_priv(dev); >
Re: [PATCH v3 05/13] firmware: scmi: install base protocol to SCMI agent
Hello Akashi-san, Some minor comments. > From: AKASHI Takahiro > Sent: Friday, September 8, 2023 04:51 > > SCMI base protocol is mandatory, and once SCMI node is found in a device > tree, the protocol handle (udevice) is unconditionally installed to > the agent. Then basic information will be retrieved from SCMI server via > the protocol and saved into the agent instance's local storage. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > Reviewed-by: Etienne Carriere > --- > v3 > * typo fix: add '@' for argument name in function description > * eliminate dev_get_uclass_plat()'s repeated in inline > * modify the code for dynamically allocated sub-vendor/agent names > v2 > * use helper functions, removing direct uses of ops > --- > drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++ > include/scmi_agent-uclass.h | 66 > 2 files changed, 182 insertions(+) > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index e823d105a3eb..87a667d60124 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev, > } > > switch (id) { > + case SCMI_PROTOCOL_ID_BASE: > + proto = priv->base_dev; > + break; > case SCMI_PROTOCOL_ID_CLOCK: > proto = priv->clock_dev; > break; > @@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev, > } > > switch (proto_id) { > + case SCMI_PROTOCOL_ID_BASE: > + priv->base_dev = proto; > + break; > case SCMI_PROTOCOL_ID_CLOCK: > priv->clock_dev = proto; > break; > @@ -237,6 +243,83 @@ int devm_scmi_process_msg(struct udevice *dev, struct > scmi_msg *msg) > return scmi_process_msg(protocol->parent, priv->channel, msg); > } > > +/** > + * scmi_fill_base_info - get base information about SCMI server > + * @agent: SCMI agent device > + * @dev: SCMI protocol device > + * > + * By using Base protocol commands, collect the base information > + * about SCMI server. > + * > + * Return: 0 on success, error code otherwise > + */ > +static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev) > +{ > + struct scmi_agent_priv *priv = dev_get_uclass_plat(agent); > + int ret; > + > + ret = scmi_base_protocol_version(dev, &priv->version); > + if (ret) { > + dev_err(dev, "protocol_version() failed (%d)\n", ret); > + return ret; > + } > + /* check for required version */ > + if (priv->version < SCMI_BASE_PROTOCOL_VERSION) { > + dev_err(dev, "base protocol version (%d) lower than > expected\n", > + priv->version); > + return -EPROTO; > + } > + > + ret = scmi_base_protocol_attrs(dev, &priv->num_agents, > + &priv->num_protocols); > + if (ret) { > + dev_err(dev, "protocol_attrs() failed (%d)\n", ret); > + return ret; > + } > + ret = scmi_base_discover_vendor(dev, &priv->vendor); > + if (ret) { > + dev_err(dev, "base_discover_vendor() failed (%d)\n", ret); > + return ret; > + } > + ret = scmi_base_discover_sub_vendor(dev, &priv->sub_vendor); > + if (ret) { > + if (ret != -EOPNOTSUPP) { > + dev_err(dev, "base_discover_sub_vendor() failed > (%d)\n", > + ret); > + return ret; > + } > + priv->sub_vendor = "NA"; > + } > + ret = scmi_base_discover_impl_version(dev, &priv->impl_version); > + if (ret) { > + dev_err(dev, "base_discover_impl_version() failed (%d)\n", > + ret); > + return ret; > + } > + > + priv->agent_id = 0x; /* to avoid false claim */ I think this line should move in below instruction block, next to priv->agent_name = "NA", for consistency, > + ret = scmi_base_discover_agent(dev, 0x, > + &priv->agent_id, &priv->agent_name); > + if (ret) { > + i
Re: [PATCH v3 05/13] firmware: scmi: install base protocol to SCMI agent
> From: AKASHI Takahiro > Sent: Friday, September 8, 2023 04:51 > > SCMI base protocol is mandatory, and once SCMI node is found in a device > tree, the protocol handle (udevice) is unconditionally installed to > the agent. Then basic information will be retrieved from SCMI server via > the protocol and saved into the agent instance's local storage. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > Reviewed-by: Etienne Carriere > --- > v3 > * typo fix: add '@' for argument name in function description > * eliminate dev_get_uclass_plat()'s repeated in inline > * modify the code for dynamically allocated sub-vendor/agent names > v2 > * use helper functions, removing direct uses of ops > --- For info, I see that this patch, as placed in this PATCH v3 series, breaks pytest. Patch v3 08/13 ("firmware: scmi: fake base protocol commands on sandbox") and patch v3 09/13 ("test: dm: simplify SCMI unit test on sandbox") should be picked before to have scmi DM pytest running. BR, etienne
Re: [PATCH v3 13/13] test: dm: add scmi command test
> From: AKASHI Takahiro > Sent: Friday, September 8, 2023 04:51 > > In this test, "scmi" command is tested against different sub-commands. > Please note that scmi command is for debug purpose and is not intended > in production system. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > Reviewed-by: Etienne Carriere > --- > v3 > * change char to u8 in vendor/agent names > v2 > * use helper functions, removing direct uses of ops > --- This change breaks pytest ut_dm_dm_test_scmi_cmd. CONFIG_CMD_SCMI=y is missing in sandbox_defconfig. > test/dm/scmi.c | 62 ++ > 1 file changed, 57 insertions(+), 5 deletions(-) > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > index 0785948186f0..423b6ef70b29 100644 > --- a/test/dm/scmi.c > +++ b/test/dm/scmi.c > @@ -104,8 +104,7 @@ static int dm_test_scmi_base(struct unit_test_state *uts) > struct scmi_agent_priv *priv; > u32 version, num_agents, num_protocols, impl_version; > u32 attributes, agent_id; > - char *vendor, *agent_name; > - u8 *protocols; > + u8 *vendor, *agent_name, *protocols; Could you squash these fixups into patch 10/13 ("test: dm: add SCMI base protocol test") unlesswhat that patch makes sandbox test build to fail. > int ret; > > /* preparation */ > @@ -134,9 +133,9 @@ static int dm_test_scmi_base(struct unit_test_state *uts) > free(vendor); > > /* message attributes */ > - ret = scmi_protocol_message_attrs(base, > - SCMI_BASE_DISCOVER_SUB_VENDOR, > - &attributes); > + ret = scmi_base_protocol_message_attrs(base, > + SCMI_BASE_DISCOVER_SUB_VENDOR, > + &attributes); Same here. BR, etienne > ut_assertok(ret); > ut_assertok(attributes); > > @@ -207,6 +206,59 @@ static int dm_test_scmi_base(struct unit_test_state *uts) > > DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT); > > +static int dm_test_scmi_cmd(struct unit_test_state *uts) > +{ > + struct udevice *agent_dev; > + > + /* preparation */ > + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", > + &agent_dev)); > + ut_assertnonnull(agent_dev); > + > + /* scmi info */ > + ut_assertok(run_command("scmi info", 0)); > + > + ut_assert_nextline("SCMI device: scmi"); > + ut_assert_nextline(" protocol version: 0x2"); > + ut_assert_nextline(" # of agents: 2"); > + ut_assert_nextline(" 0: platform"); > + ut_assert_nextline(" > 1: OSPM"); > + ut_assert_nextline(" # of protocols: 3"); > + ut_assert_nextline(" Clock management"); > + ut_assert_nextline(" Reset domain management"); > + ut_assert_nextline(" Voltage domain management"); > + ut_assert_nextline(" vendor: U-Boot"); > + ut_assert_nextline(" sub vendor: Sandbox"); > + ut_assert_nextline(" impl version: 0x1"); > + > + ut_assert_console_end(); > + > + /* scmi perm_dev */ > + ut_assertok(run_command("scmi perm_dev 1 0 1", 0)); > + ut_assert_console_end(); > + > + ut_assert(run_command("scmi perm_dev 1 0 0", 0)); > + ut_assert_nextline("Denying access to device:0 failed (-13)"); > + ut_assert_console_end(); > + > + /* scmi perm_proto */ > + ut_assertok(run_command("scmi perm_proto 1 0 14 1", 0)); > + ut_assert_console_end(); > + > + ut_assert(run_command("scmi perm_proto 1 0 14 0", 0)); > + ut_assert_nextline("Denying access to protocol:0x14 on device:0 > failed (-13)"); > + ut_assert_console_end(); > + > + /* scmi reset */ > + ut_assert(run_command("scmi reset 1 1", 0)); > + ut_assert_nextline("Reset failed (-13)"); > + ut_assert_console_end(); > + > + return 0; > +} > + > +DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT); > + > static int dm_test_scmi_clocks(struct unit_test_state *uts) > { > struct sandbox_scmi_agent *agent; > -- > 2.34.1 >
Re: [PATCH v9 05/15] stm32mp1: dk2: Add image information for capsule updates
Hello Sughosh, On Fri, 26 Aug 2022 at 11:57, Sughosh Ganu wrote: > > Enabling capsule update functionality on the platform requires > populating information on the images that are to be updated using the > functionality. Do so for the DK2 board. > > Signed-off-by: Sughosh Ganu > --- > Changes since V8: > * Use STM32MP_FIP_IMAGE_GUID for the FIP GUID value as suggested by > Yann > > board/st/stm32mp1/stm32mp1.c | 23 +++ > include/configs/stm32mp15_common.h | 4 > 2 files changed, 27 insertions(+) > > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > index 9496890d16..bfec0a710d 100644 > --- a/board/st/stm32mp1/stm32mp1.c > +++ b/board/st/stm32mp1/stm32mp1.c > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -87,6 +88,16 @@ > #define USB_START_LOW_THRESHOLD_UV 123 > #define USB_START_HIGH_THRESHOLD_UV215 > > +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) > +struct efi_fw_image fw_images[1]; > + > +struct efi_capsule_update_info update_info = { > + .images = fw_images, > +}; > + > +u8 num_image_type_guids = ARRAY_SIZE(fw_images); > +#endif /* EFI_HAVE_CAPSULE_SUPPORT */ > + > int board_early_init_f(void) > { > /* nothing to do, only used in SPL */ > @@ -670,6 +681,18 @@ int board_init(void) > > setup_led(LEDST_ON); > > +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) > + if (board_is_stm32mp15x_dk2()) { Sorry for this late comment. Should this be restricted to mp15-dk2? I would remove the test and apply when CONFIG_EFI_HAVE_CAPSULE_SUPPORT is enable. > + efi_guid_t image_type_guid = STM32MP_FIP_IMAGE_GUID; > + guidcpy(&fw_images[0].image_type_id, &image_type_guid); > + fw_images[0].fw_name = u"STM32MP-FIP"; > + /* > +* For FWU multi bank update, the image > +* index will be computed at runtime > +*/ > + fw_images[0].image_index = 0; > + } > +#endif > return 0; > } > > diff --git a/include/configs/stm32mp15_common.h > b/include/configs/stm32mp15_common.h > index c5412ffeb3..bb19dae945 100644 > --- a/include/configs/stm32mp15_common.h > +++ b/include/configs/stm32mp15_common.h > @@ -34,6 +34,10 @@ > #define CONFIG_SERVERIP 192.168.1.1 > #endif > > +#define STM32MP_FIP_IMAGE_GUID \ > + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \ > +0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) > + > > /*/ > #ifdef CONFIG_DISTRO_DEFAULTS > > /*/ > -- > 2.34.1 >
Re: [PATCH v9 09/15] FWU: Add boot time checks as highlighted by the FWU specification
On Fri, 26 Aug 2022 at 11:58, Sughosh Ganu wrote: > > The FWU Multi Bank Update specification requires the Update Agent to > carry out certain checks at the time of platform boot. The Update > Agent is the component which is responsible for updating the firmware > components and maintaining and keeping the metadata in sync. > > The spec requires that the Update Agent perform the following checks > at the time of boot > * Sanity check of both the metadata copies maintained by the platform. > * Get the boot index passed to U-Boot by the prior stage bootloader > and use this value for metadata bookkeeping. > * Check if the system is booting in Trial State. If the system boots > in the Trial State for more than a specified number of boot counts, > change the Active Bank to be booting the platform from. > > Call these checks through the main loop event at the time of platform > boot. > > Signed-off-by: Sughosh Ganu > --- > Changes since V8: > * Call fwu_boottime_checks through the event interface > * Add comments for API functions > > include/fwu.h | 13 +++ > lib/efi_loader/efi_setup.c | 1 + > lib/fwu_updates/fwu.c | 189 - > 3 files changed, 202 insertions(+), 1 deletion(-) > > diff --git a/include/fwu.h b/include/fwu.h > index b8c207deaf..31c9923ff5 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -252,4 +252,17 @@ int fwu_plat_get_update_index(uint *update_idx); > * > */ > void fwu_plat_get_bootidx(void *boot_idx); > + > +/** > + * fwu_update_checks_pass() - Check if FWU update can be done > + * > + * Check if the FWU update can be executed. The updates are > + * allowed only when the platform is not in Trial State and > + * the boot time checks have passed > + * > + * Return: 1 if OK, 0 on error > + * > + */ > +u8 fwu_update_checks_pass(void); > + > #endif /* _FWU_H_ */ > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c > index 751beda590..23dc7a0710 100644 > --- a/lib/efi_loader/efi_setup.c > +++ b/lib/efi_loader/efi_setup.c > @@ -199,6 +199,7 @@ static efi_status_t __efi_init_early(void) > goto out; > > ret = efi_disk_init(); > + > out: > return ret; > } > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 94b15859a5..27f48855af 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -4,10 +4,19 @@ > */ > > #include > +#include > #include > +#include > +#include > #include > #include > -#include > +#include > + > +#include > +#include > + > +static u8 trial_state; > +static u8 boottime_check; > > #include > #include > @@ -16,6 +25,112 @@ > #define IMAGE_ACCEPT_SET BIT(0) > #define IMAGE_ACCEPT_CLEAR BIT(1) > > +static int trial_counter_update(u16 *trial_state_ctr) > +{ > + bool delete; > + u32 var_attr; > + efi_status_t status; > + efi_uintn_t var_size; > + > + delete = !trial_state_ctr ? true : false; > + var_size = !trial_state_ctr ? 0 : > (efi_uintn_t)sizeof(*trial_state_ctr); > + var_attr = !trial_state_ctr ? 0 : EFI_VARIABLE_NON_VOLATILE | > + EFI_VARIABLE_BOOTSERVICE_ACCESS; > + status = efi_set_variable_int(u"TrialStateCtr", > + &efi_global_variable_guid, > + var_attr, > + var_size, trial_state_ctr, false); > + > + if ((delete && (status != EFI_NOT_FOUND && > + status != EFI_SUCCESS)) || > + (!delete && status != EFI_SUCCESS)) > + return -1; > + > + return 0; > +} > + > +static int in_trial_state(struct fwu_mdata *mdata) > +{ > + u32 i, active_bank; > + struct fwu_image_entry *img_entry; > + struct fwu_image_bank_info *img_bank_info; > + > + active_bank = mdata->active_index; > + img_entry = &mdata->img_entry[0]; > + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { > + img_bank_info = &img_entry[i].img_bank_info[active_bank]; > + if (!img_bank_info->accepted) { > + return 1; > + } > + } > + > + return 0; > +} > + > +static int fwu_trial_state_check(struct udevice *dev) > +{ > + int ret; > + efi_status_t status; > + efi_uintn_t var_size; > + u16 trial_state_ctr; > + u32 var_attributes, active_idx; > + struct fwu_mdata mdata = { 0 }; > + > + ret = fwu_get_mdata(dev, &mdata); > + if (ret) > + return ret; > + > + if ((trial_state = in_trial_state(&mdata))) { > + var_size = (efi_uintn_t)sizeof(trial_state_ctr); > + log_info("System booting in Trial State\n"); > + var_attributes = EFI_VARIABLE_NON_VOLATILE | > + EFI_VARIABLE_BOOTSERVICE_ACCESS; > + status = efi_get_variable_int(u"TrialStateCtr", > +
Re: [PATCH v9 09/15] FWU: Add boot time checks as highlighted by the FWU specification
Hi Sughosh, Reviewed-by: Etienne Carriere with a minor comment. On Fri, 26 Aug 2022 at 11:58, Sughosh Ganu wrote: > > The FWU Multi Bank Update specification requires the Update Agent to > carry out certain checks at the time of platform boot. The Update > Agent is the component which is responsible for updating the firmware > components and maintaining and keeping the metadata in sync. > > The spec requires that the Update Agent perform the following checks > at the time of boot > * Sanity check of both the metadata copies maintained by the platform. > * Get the boot index passed to U-Boot by the prior stage bootloader > and use this value for metadata bookkeeping. > * Check if the system is booting in Trial State. If the system boots > in the Trial State for more than a specified number of boot counts, > change the Active Bank to be booting the platform from. > > Call these checks through the main loop event at the time of platform > boot. > > Signed-off-by: Sughosh Ganu > --- > Changes since V8: > * Call fwu_boottime_checks through the event interface > * Add comments for API functions > > include/fwu.h | 13 +++ > lib/efi_loader/efi_setup.c | 1 + > lib/fwu_updates/fwu.c | 189 - > 3 files changed, 202 insertions(+), 1 deletion(-) > > diff --git a/include/fwu.h b/include/fwu.h > index b8c207deaf..31c9923ff5 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -252,4 +252,17 @@ int fwu_plat_get_update_index(uint *update_idx); > * > */ > void fwu_plat_get_bootidx(void *boot_idx); > + > +/** > + * fwu_update_checks_pass() - Check if FWU update can be done > + * > + * Check if the FWU update can be executed. The updates are > + * allowed only when the platform is not in Trial State and > + * the boot time checks have passed > + * > + * Return: 1 if OK, 0 on error > + * > + */ > +u8 fwu_update_checks_pass(void); > + > #endif /* _FWU_H_ */ > diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c > index 751beda590..23dc7a0710 100644 > --- a/lib/efi_loader/efi_setup.c > +++ b/lib/efi_loader/efi_setup.c > @@ -199,6 +199,7 @@ static efi_status_t __efi_init_early(void) > goto out; > > ret = efi_disk_init(); > + > out: > return ret; > } > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 94b15859a5..27f48855af 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -4,10 +4,19 @@ > */ > > #include > +#include > #include > +#include > +#include > #include > #include > -#include > +#include > + > +#include > +#include > + > +static u8 trial_state; > +static u8 boottime_check; > > #include > #include > @@ -16,6 +25,112 @@ > #define IMAGE_ACCEPT_SET BIT(0) > #define IMAGE_ACCEPT_CLEAR BIT(1) > > +static int trial_counter_update(u16 *trial_state_ctr) > +{ > + bool delete; > + u32 var_attr; > + efi_status_t status; > + efi_uintn_t var_size; > + > + delete = !trial_state_ctr ? true : false; > + var_size = !trial_state_ctr ? 0 : > (efi_uintn_t)sizeof(*trial_state_ctr); > + var_attr = !trial_state_ctr ? 0 : EFI_VARIABLE_NON_VOLATILE | > + EFI_VARIABLE_BOOTSERVICE_ACCESS; > + status = efi_set_variable_int(u"TrialStateCtr", > + &efi_global_variable_guid, > + var_attr, > + var_size, trial_state_ctr, false); > + > + if ((delete && (status != EFI_NOT_FOUND && > + status != EFI_SUCCESS)) || > + (!delete && status != EFI_SUCCESS)) > + return -1; > + > + return 0; > +} > + > +static int in_trial_state(struct fwu_mdata *mdata) > +{ > + u32 i, active_bank; > + struct fwu_image_entry *img_entry; > + struct fwu_image_bank_info *img_bank_info; > + > + active_bank = mdata->active_index; > + img_entry = &mdata->img_entry[0]; > + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { > + img_bank_info = &img_entry[i].img_bank_info[active_bank]; > + if (!img_bank_info->accepted) { > + return 1; > + } > + } > + > + return 0; > +} > + > +static int fwu_trial_state_check(struct udevice *dev) > +{ > + int ret; > + efi_status_t status; > + efi_uintn_t var_size; > + u16 trial_state_ctr; > + u32 var_attributes, act
Re: [PATCH v9 03/15] FWU: Add FWU metadata access driver for GPT partitioned block devices
Hi Sughosh, Reviewed-by: Etienne Carriere with comment addressed. On Fri, 26 Aug 2022 at 11:57, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > updatable images is stored as part of the metadata, on a separate > partition. Add a driver for reading from and writing to the metadata > when the updatable images and the metadata are stored on a block > device which is formated with GPT based partition scheme. formatted > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > --- > Changes since V8: > * Rename fwu_mdata_gpt_blk.c as gpt_blk.c as suggested by Simon > * Use natural integer types instead of specific width integers as > suggested by Simon > * Fix return codes as suggested by Simon > * Code cleanup of some superfluous error checks, like for > dev_get_uclass_plat() function > * Use blk_get_from_parent() for getting the parent of the block device > containing the FWU metadata > * Add comments to the API functions > > drivers/fwu-mdata/Kconfig | 16 ++ > drivers/fwu-mdata/Makefile | 8 + > drivers/fwu-mdata/gpt_blk.c | 378 > include/fwu.h | 4 + > 4 files changed, 406 insertions(+) > create mode 100644 drivers/fwu-mdata/Kconfig > create mode 100644 drivers/fwu-mdata/Makefile > create mode 100644 drivers/fwu-mdata/gpt_blk.c > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > new file mode 100644 > index 00..7322da48b1 > --- /dev/null > +++ b/drivers/fwu-mdata/Kconfig > @@ -0,0 +1,16 @@ > +config FWU_MDATA > + bool "Driver support for accessing FWU Metadata" > + depends on DM > + help > + Enable support for accessing FWU Metadata partitions. The > + FWU Metadata partitions reside on the same storage device > + which contains the other FWU updatable firmware images. > + > +config FWU_MDATA_GPT_BLK > + bool "FWU Metadata access for GPT partitioned Block devices" > + select PARTITION_TYPE_GUID > + select PARTITION_UUIDS > + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION > + help > + Enable support for accessing FWU Metadata on GPT partitioned > + block devices. > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > new file mode 100644 > index 00..3fee64c10c > --- /dev/null > +++ b/drivers/fwu-mdata/Makefile > @@ -0,0 +1,8 @@ > +# SPDX-License-Identifier: GPL-2.0-or-later > +# > +# Copyright (c) 2022, Linaro Limited > +# > + > + > +obj-$(CONFIG_FWU_MDATA) += fwu-mdata-uclass.o > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += gpt_blk.o > diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c > new file mode 100644 > index 00..4f0558825b > --- /dev/null > +++ b/drivers/fwu-mdata/gpt_blk.c > @@ -0,0 +1,378 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#define LOG_CATEGORY UCLASS_FWU_MDATA > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#define PRIMARY_PART BIT(0) > +#define SECONDARY_PART BIT(1) > +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) > + > +#define MDATA_READ BIT(0) > +#define MDATA_WRITEBIT(1) > + > +static int gpt_get_mdata_partitions(struct blk_desc *desc, > + uint *primary_mpart, > + uint *secondary_mpart) > +{ > + int i, ret; > + u32 mdata_parts; > + efi_guid_t part_type_guid; > + struct disk_partition info; > + const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID; > + > + mdata_parts = 0; > + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { > + if (part_get_info(desc, i, &info)) > + continue; > + uuid_str_to_bin(info.type_guid, part_type_guid.b, > + UUID_STR_FORMAT_GUID); > + > + if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) { > + ++mdata_parts; > + if (!*primary_mpart) > + *primary_mpart = i; > + else > + *secondary_mpart = i; > + } > + } > + > + if (mdata_parts != 2) { > + log_debug("Expect two copies of the FWU metadata instead of > %d\n", > +
Re: [PATCH v9 07/15] FWU: STM32MP1: Add support to read boot index from backup register
Hi Sughosh, I have a last comment on this series, related to the below patch and patch "test: dm: Add test cases for FWU Metadata uclass". On Fri, 26 Aug 2022 at 11:58, Sughosh Ganu wrote: > > The FWU Multi Bank Update feature allows the platform to boot the > firmware images from one of the partitions(banks). The first stage > bootloader(fsbl) passes the value of the boot index, i.e. the bank > from which the firmware images were booted from to U-Boot. On the > STM32MP157C-DK2 board, this value is passed through one of the SoC's > backup register. Add a function to read the boot index value from the > backup register. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Acked-by: Ilias Apalodimas > --- > Changes since V8: None > > arch/arm/mach-stm32mp/include/mach/stm32.h | 5 + > board/st/stm32mp1/stm32mp1.c | 23 ++ > include/fwu.h | 12 +++ > 3 files changed, 40 insertions(+) > > diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h > b/arch/arm/mach-stm32mp/include/mach/stm32.h > index c70375a723..c85ae6a34e 100644 > --- a/arch/arm/mach-stm32mp/include/mach/stm32.h > +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h > @@ -112,11 +112,16 @@ enum boot_device { > #ifdef CONFIG_STM32MP15x > #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) > #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) > +#define TAMP_FWU_BOOT_INFO_REG TAMP_BACKUP_REGISTER(10) > #define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) > #define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) > #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) > #define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21) > > +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) > + > +#define TAMP_FWU_BOOT_IDX_OFFSET 0 > + > #define TAMP_COPRO_STATE_OFF 0 > #define TAMP_COPRO_STATE_INIT 1 > #define TAMP_COPRO_STATE_CRUN 2 > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > index bfec0a710d..dd95babb49 100644 > --- a/board/st/stm32mp1/stm32mp1.c > +++ b/board/st/stm32mp1/stm32mp1.c > @@ -966,3 +966,26 @@ static void board_copro_image_process(ulong fw_image, > size_t fw_size) > } > > U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); > + > +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) > + > +#include > + > +/** > + * fwu_plat_get_bootidx() - Get the value of the boot index > + * @boot_idx: Boot index value > + * > + * Get the value of the bank(partition) from which the platform > + * has booted. This value is passed to U-Boot from the earlier > + * stage bootloader which loads and boots all the relevant > + * firmware images > + * > + */ > +void fwu_plat_get_bootidx(void *boot_idx) > +{ > + u32 *bootidx = boot_idx; > + > + *bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >> > + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; > +} > +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ > diff --git a/include/fwu.h b/include/fwu.h > index 7ebd3a7115..b8c207deaf 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -240,4 +240,16 @@ int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t > *image_guid, > * > */ > int fwu_plat_get_update_index(uint *update_idx); > + > +/** > + * fwu_plat_get_bootidx() - Get the value of the boot index > + * @boot_idx: Boot index value > + * > + * Get the value of the bank(partition) from which the platform > + * has booted. This value is passed to U-Boot from the earlier > + * stage bootloader which loads and boots all the relevant > + * firmware images > + * > + */ > +void fwu_plat_get_bootidx(void *boot_idx); It's maybe not clean to pass a void * to something callee shall write to. Could the reference be passed with an explicit type pointer as 'unsigned int *'? Best regards, Etienne > #endif /* _FWU_H_ */ > -- > 2.34.1 >
Re: [PATCH v9 01/15] dt/bindings: Add bindings for GPT based FWU Metadata storage device
On Fri, 26 Aug 2022 at 11:57, Sughosh Ganu wrote: > > Add bindings needed for accessing the FWU metadata partitions. These > include the compatible string which point to the access method and the > actual device which stores the FWU metadata. > > The current patch adds basic bindings needed for accessing the > metadata structure on GPT partitioned block devices. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Heinrich Schuchardt > --- > Changes since V8: None > > .../firmware/fwu-mdata-gpt.yaml | 32 +++ > 1 file changed, 32 insertions(+) > create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml > Acked-by: Etienne Carriere > diff --git a/doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml > b/doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml > new file mode 100644 > index 00..0735191ff1 > --- /dev/null > +++ b/doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml > @@ -0,0 +1,32 @@ > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/firmware/fwu-mdata-gpt.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: FWU metadata on device with GPT partitioned layout > + > +maintainers: > + - Sughosh Ganu > + > +properties: > + compatible: > +items: > + - const: u-boot,fwu-mdata-gpt > + > + fwu-mdata-store: > +maxItems: 1 > +description: Phandle of the device which contains the FWU medatata > partition. > + > +required: > + - compatible > + - fwu-mdata-store > + > +additionalProperties: false > + > +examples: > + - | > +fwu-mdata { > +compatible = "u-boot,fwu-mdata-gpt"; > +fwu-mdata-store = <&sdmmc1>; > +}; > -- > 2.34.1 >
Re: [PATCH v9 02/15] FWU: Add FWU metadata structure and driver for accessing metadata
On Fri, 26 Aug 2022 at 11:57, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > updatable images is stored as part of the metadata, which is stored on > a dedicated partition. Add the metadata structure, and a driver model > uclass which provides functions to access the metadata. These are > generic API's, and implementations can be added based on parameters > like how the metadata partition is accessed and what type of storage > device houses the metadata. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > --- > Changes since V8: > * Declare the metadata struct on the stack rather than heap > * Move the API's to fwu.c and only keep the DM ops in the uclass > driver > * Fix return codes as suggested by Simon > * Change log_err to log_debug as suggested by Simon > * Remove the __packed attribute on the metadata structures as > suggested by Simon > * Add comments to the API functions Reviewed-by: Etienne Carriere > > drivers/fwu-mdata/fwu-mdata-uclass.c | 107 > include/dm/uclass-id.h | 1 + > include/fwu.h| 210 > include/fwu_mdata.h | 67 + > lib/fwu_updates/fwu.c| 357 +++ > 5 files changed, 742 insertions(+) > create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c > create mode 100644 include/fwu.h > create mode 100644 include/fwu_mdata.h > create mode 100644 lib/fwu_updates/fwu.c > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > b/drivers/fwu-mdata/fwu-mdata-uclass.c > new file mode 100644 > index 00..65ae93c21f > --- /dev/null > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > @@ -0,0 +1,107 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#define LOG_CATEGORY UCLASS_FWU_MDATA > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +/** > + * fwu_mdata_check() - Check if the FWU metadata is valid > + * @dev: FWU metadata device > + * > + * Validate both copies of the FWU metadata. If one of the copies > + * has gone bad, restore it from the other bad copy. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_mdata_check(struct udevice *dev) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->mdata_check) { > + log_debug("mdata_check() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->mdata_check(dev); > +} > + > +/** > + * fwu_get_mdata() - Get a FWU metadata copy > + * @dev: FWU metadata device > + * @mdata: Copy of the FWU metadata > + * > + * Get a valid copy of the FWU metadata. > + * > + * Note: This function is to be called first when modifying any fields > + * in the metadata. The sequence of calls to modify any field in the > + * metadata would be 1) fwu_get_mdata 2) Modify metadata, followed by > + * 3) fwu_update_mdata > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_get_mdata(struct udevice *dev, struct fwu_mdata *mdata) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->get_mdata) { > + log_debug("get_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->get_mdata(dev, mdata); > +} > + > +/** > + * fwu_update_mdata() - Update the FWU metadata > + * @dev: FWU metadata device > + * @mdata: Copy of the FWU metadata > + * > + * Update the FWU metadata structure by writing to the > + * FWU metadata partitions. > + * > + * Note: This function is not to be called directly to update the > + * metadata fields. The sequence of function calls should be > + * 1) fwu_get_mdata() 2) Modify the medata fields 3) fwu_update_mdata() > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_update_mdata(struct udevice *dev, struct fwu_mdata *mdata) > +{ > + void *buf; > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->update_mdata) { > + log_debug("get_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + /* > +* Calculate the crc32 for the updated FWU metadata > +* and put the updated value in the FWU metadata crc32 > +* field > +*/ > + buf = &mdata->version; > + mdata->crc32 = crc32(0, buf, sizeof(*mdata)
Re: [PATCH v9 04/15] stm32mp1: dk2: Add a node for the FWU metadata device
On Fri, 26 Aug 2022 at 11:57, Sughosh Ganu wrote: > > The FWU metadata structure is accessed through the driver model > interface. On the stm32mp157c-dk2 board, the FWU metadata is stored on > the uSD card. Add the fwu-mdata node on the u-boot specifc dtsi file > for accessing the metadata structure. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Acked-by: Ilias Apalodimas > --- > Changes since V8: None Acked-by: Etienne Carriere > > arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 +++ > 1 file changed, 7 insertions(+) > > diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi > b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi > index 06ef3a4095..24f86209db 100644 > --- a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi > +++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi > @@ -4,3 +4,10 @@ > */ > > #include "stm32mp157a-dk1-u-boot.dtsi" > + > +/ { > + fwu-mdata { > + compatible = "u-boot,fwu-mdata-gpt"; > + fwu-mdata-store = <&sdmmc1>; > + }; > +}; > -- > 2.34.1 >
Re: [PATCH v9 06/15] FWU: Add helper functions for accessing FWU metadata
On Fri, 26 Aug 2022 at 11:57, Sughosh Ganu wrote: > > Add weak functions for getting the update index value and dfu > alternate number needed for FWU Multi Bank update > functionality. > > The current implementation for getting the update index value is for > platforms with 2 banks. If a platform supports more than 2 banks, it > can implement it's own function. The function to get the dfu alternate > number has been added for platforms with GPT partitioned storage > devices. Platforms with other storage partition scheme need to > implement their own function. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > --- > Changes since V8: > * Add comments for API functions > * Update the logic to get the update index as suggested by Jassi Acked-by: Etienne Carriere > > include/fwu.h | 29 ++ > lib/fwu_updates/fwu.c | 27 + > lib/fwu_updates/fwu_gpt.c | 115 ++ > 3 files changed, 171 insertions(+) > create mode 100644 lib/fwu_updates/fwu_gpt.c > > diff --git a/include/fwu.h b/include/fwu.h > index ecabf11210..7ebd3a7115 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -211,4 +211,33 @@ int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); > */ > int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); > > +/** > + * fwu_plat_get_alt_num() - Get the DFU Alt Num for the image from the > platform > + * @dev: FWU device > + * @image_guid: Image GUID for which DFU alt number needs to be retrieved > + * @alt_num: Pointer to the alt_num > + * > + * Get the DFU alt number from the platform for the image specified by the > + * image GUID. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, > +int *alt_num); > + > +/** > + * fwu_plat_get_update_index() - Get the value of the update bank > + * @update_idx: Bank number to which images are to be updated > + * > + * Get the value of the bank(partition) to which the update needs to be > + * made. > + * > + * Note: This is a weak function and platforms can override this with > + * their own implementation for selection of the update bank. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_plat_get_update_index(uint *update_idx); > #endif /* _FWU_H_ */ > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index a871d77b4c..94b15859a5 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -355,3 +355,30 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 > bank) > return fwu_clrset_image_accept(img_type_id, bank, >IMAGE_ACCEPT_CLEAR); > } > + > +/** > + * fwu_plat_get_update_index() - Get the value of the update bank > + * @update_idx: Bank number to which images are to be updated > + * > + * Get the value of the bank(partition) to which the update needs to be > + * made. > + * > + * Note: This is a weak function and platforms can override this with > + * their own implementation for selection of the update bank. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +__weak int fwu_plat_get_update_index(uint *update_idx) > +{ > + int ret; > + u32 active_idx; > + > + ret = fwu_get_active_index(&active_idx); > + if (ret < 0) > + return -1; > + > + *update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS; > + > + return ret; > +} > diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c > new file mode 100644 > index 00..a3134b80c9 > --- /dev/null > +++ b/lib/fwu_updates/fwu_gpt.c > @@ -0,0 +1,115 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t > *image_guid) > +{ > + int i; > + struct disk_partition info; > + efi_guid_t unique_part_guid; > + > + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { > + if (part_get_info(desc, i, &info)) > + continue; > + uuid_str_to_bin(info.uuid, unique_part_guid.b, > + UUID_STR_FORMAT_GUID); > + > + if (!guidcmp(&unique_part_guid, image_guid)) > + return i; > + } > + > + log_err("No partition found with image_guid %pUs\n", image_guid); >
Re: [PATCH v9 11/15] FWU: cmd: Add a command to read FWU metadata
On Fri, 26 Aug 2022 at 11:58, Sughosh Ganu wrote: > > Add a command to read the metadata as specified in the FWU > specification and print the fields of the metadata. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Ilias Apalodimas > --- > Changes since V8: None > > cmd/Kconfig | 6 > cmd/Makefile| 1 + > cmd/fwu_mdata.c | 79 + > 3 files changed, 86 insertions(+) > create mode 100644 cmd/fwu_mdata.c Reviewed-by: Etienne Carriere > > diff --git a/cmd/Kconfig b/cmd/Kconfig > index 211ebe9c87..3abc60b63e 100644 > --- a/cmd/Kconfig > +++ b/cmd/Kconfig > @@ -161,6 +161,12 @@ config CMD_CPU > internal name) and clock frequency. Other information may be > available depending on the CPU driver. > > +config CMD_FWU_METADATA > + bool "fwu metadata read" > + depends on FWU_MULTI_BANK_UPDATE > + help > + Command to read the metadata and dump it's contents > + > config CMD_LICENSE > bool "license" > select BUILD_BIN2C > diff --git a/cmd/Makefile b/cmd/Makefile > index 6e87522b62..ff6e160f4a 100644 > --- a/cmd/Makefile > +++ b/cmd/Makefile > @@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_FPGA) += fpga.o > obj-$(CONFIG_CMD_FPGAD) += fpgad.o > obj-$(CONFIG_CMD_FS_GENERIC) += fs.o > obj-$(CONFIG_CMD_FUSE) += fuse.o > +obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o > obj-$(CONFIG_CMD_GETTIME) += gettime.o > obj-$(CONFIG_CMD_GPIO) += gpio.o > obj-$(CONFIG_CMD_HVC) += smccc.o > diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c > new file mode 100644 > index 00..725b4c17d3 > --- /dev/null > +++ b/cmd/fwu_mdata.c > @@ -0,0 +1,79 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +static void print_mdata(struct fwu_mdata *mdata) > +{ > + int i, j; > + struct fwu_image_entry *img_entry; > + struct fwu_image_bank_info *img_info; > + > + printf("\tFWU Metadata\n"); > + printf("crc32: %#x\n", mdata->crc32); > + printf("version: %#x\n", mdata->version); > + printf("active_index: %#x\n", mdata->active_index); > + printf("previous_active_index: %#x\n", mdata->previous_active_index); > + > + printf("\tImage Info\n"); > + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { > + img_entry = &mdata->img_entry[i]; > + printf("\nImage Type Guid: %pUL\n", > + &img_entry->image_type_uuid); > + printf("Location Guid: %pUL\n", &img_entry->location_uuid); > + for (j = 0; j < CONFIG_FWU_NUM_BANKS; j++) { > + img_info = &img_entry->img_bank_info[j]; > + printf("Image Guid: %pUL\n", &img_info->image_uuid); > + printf("Image Acceptance: %s\n", > + img_info->accepted == 0x1 ? "yes" : "no"); > + } > + } > +} > + > +int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, > +int argc, char * const argv[]) > +{ > + struct udevice *dev; > + int ret = CMD_RET_SUCCESS, res; > + struct fwu_mdata mdata = { 0 }; > + > + if (uclass_get_device(UCLASS_FWU_MDATA, 0, &dev) || !dev) { > + log_err("Unable to get FWU metadata device\n"); > + return CMD_RET_FAILURE; > + } > + > + res = fwu_mdata_check(dev); > + if (res < 0) { > + log_err("FWU Metadata check failed\n"); > + ret = CMD_RET_FAILURE; > + goto out; > + } > + > + res = fwu_get_mdata(dev, &mdata); > + if (res < 0) { > + log_err("Unable to get valid FWU metadata\n"); > + ret = CMD_RET_FAILURE; > + goto out; > + } > + > + print_mdata(&mdata); > + > +out: > + return ret; > +} > + > +U_BOOT_CMD( > + fwu_mdata_read, 1, 1, do_fwu_mdata_read, > + "Read and print FWU metadata", > + "" > +); > -- > 2.34.1 >
[PATCH] [RFC] lib: efi_loader: don't delete invalid handles
Changes efi_delete_handle() to not free EFI handles that are not related to EFI objects. This change tries to resolved an issue seen since U-Boot v2022.07 in which EFI ExitBootService attempts to release some EFI handles twice. The issue was seen booting a EFI shell that invokes 'connect -r' and then boots a Linux kernel. Execution of connect command makes EFI subsystem to bind a block device for each root block devices EFI handles. However these EFI device handles are already bound to a driver and we can have 2 registered devices relating to the same EFI handler. On ExitBootService, the loop removing the devices makes these EFI handles to be released twice which corrupts memory. This patch prevents the memory release operation caused by the issue but I don't think this patch is the right way to addresse the problem. Any help will be much appreciated. Signed-off-by: Etienne Carriere --- lib/efi_loader/efi_boottime.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 4da64b5d29..e38990ace2 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -619,9 +619,15 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) */ void efi_delete_handle(efi_handle_t handle) { + efi_status_t ret; + if (!handle) return; - efi_remove_all_protocols(handle); + + ret = efi_remove_all_protocols(handle); + if (ret == EFI_INVALID_PARAMETER) + return; + list_del(&handle->link); free(handle); } -- 2.25.1
Re: [PATCH] [RFC] lib: efi_loader: don't delete invalid handles
Hello Heinrich, Thanks a lot for the detailed feedback on how to address root issue. Indeed not an obvious fix. Regards, Etienne On Thu, 8 Sept 2022 at 08:03, Heinrich Schuchardt wrote: > On 9/7/22 10:20, Etienne Carriere wrote: > > Changes efi_delete_handle() to not free EFI handles that are not related > > to EFI objects. > > > > This change tries to resolved an issue seen since U-Boot v2022.07 > > in which EFI ExitBootService attempts to release some EFI handles twice. > > > > The issue was seen booting a EFI shell that invokes 'connect -r' and > > then boots a Linux kernel. Execution of connect command makes EFI > > subsystem to bind a block device for each root block devices EFI handles. > > However these EFI device handles are already bound to a driver and we > > can have 2 registered devices relating to the same EFI handler. On > > ExitBootService, the loop removing the devices makes these EFI handles > > to be released twice which corrupts memory. > > > > This patch prevents the memory release operation caused by the issue but > > I don't think this patch is the right way to addresse the problem. Any > > help will be much appreciated. > > > > Signed-off-by: Etienne Carriere > > --- > > lib/efi_loader/efi_boottime.c | 8 +++- > > 1 file changed, 7 insertions(+), 1 deletion(-) > > > > diff --git a/lib/efi_loader/efi_boottime.c > b/lib/efi_loader/efi_boottime.c > > index 4da64b5d29..e38990ace2 100644 > > --- a/lib/efi_loader/efi_boottime.c > > +++ b/lib/efi_loader/efi_boottime.c > > @@ -619,9 +619,15 @@ efi_status_t efi_remove_all_protocols(const > efi_handle_t handle) > >*/ > > void efi_delete_handle(efi_handle_t handle) > > { > > + efi_status_t ret; > > + > > if (!handle) > > return; > > The patch does not solve the underlying problem but checking the > validity of the handle makes sense anyway as we have a lot of callers. > > We can remove this check as we test the return value of > efi_remove_all_protocols(). > > > - efi_remove_all_protocols(handle); > > + > > + ret = efi_remove_all_protocols(handle); > > + if (ret == EFI_INVALID_PARAMETER) > > We should write a message here. > > log_err("Can't remove invalid handle %p\n", handle); > > Best regards > > Heinrich > > > + return; > > + > > list_del(&handle->link); > > free(handle); > > } > >
Re: [PATCH 1/1] efi_selftest: supply EFI binary for ExitBootServices
On Thu, 8 Sept 2022 at 06:52, Heinrich Schuchardt < heinrich.schucha...@canonical.com> wrote: > Calling ExitBootServices() after executing 'connect -r' in the EFI > shell has previously caused errors. > > Provide an EFI binary ebstest.efi that calls ExitBootServices() for > testing. > > Signed-off-by: Heinrich Schuchardt > --- > I just need the binary currently for testing. > Probably we will need something simulating 'connect -r' in the unit tests. > --- > Acked-by: Etienne Carriere > lib/efi_selftest/Makefile | 5 ++ > lib/efi_selftest/ebstest.c | 122 + > 2 files changed, 127 insertions(+) > create mode 100644 lib/efi_selftest/ebstest.c > > diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile > index daac6c3968..a57237c122 100644 > --- a/lib/efi_selftest/Makefile > +++ b/lib/efi_selftest/Makefile > @@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os > -ffreestanding > CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI) > CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding > CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI) > +CFLAGS_ebstest.o := $(CFLAGS_EFI) -Os -ffreestanding > +CFLAGS_REMOVE_ebstest.o := $(CFLAGS_NON_EFI) > > obj-y += \ > efi_selftest.o \ > @@ -74,6 +76,9 @@ endif > > obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o > > +always += \ > +ebstest.efi > + > targets += \ > efi_miniapp_file_image_exception.h \ > efi_miniapp_file_image_exit.h \ > diff --git a/lib/efi_selftest/ebstest.c b/lib/efi_selftest/ebstest.c > new file mode 100644 > index 00..c785671d2b > --- /dev/null > +++ b/lib/efi_selftest/ebstest.c > @@ -0,0 +1,122 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Call ExitBootServices() > + * > + * Copyright (c) 2022 Heinrich Schuchardt > + */ > + > +#include > +#include > + > +static efi_handle_t handle; > +static struct efi_system_table *systable; > +static struct efi_boot_services *boottime; > +static struct efi_simple_text_output_protocol *cout; > + > +/** > + * color() - set foreground color > + * > + * @color: foreground color > + */ > +static void color(u8 color) > +{ > + cout->set_attribute(cout, color | EFI_BACKGROUND_BLACK); > +} > + > +/** > + * print() - print string > + * > + * @string:text > + */ > +static void print(u16 *string) > +{ > + cout->output_string(cout, string); > +} > + > +/** > + * error() - print error string > + * > + * @string:error text > + */ > +static void error(u16 *string) > +{ > + color(EFI_LIGHTRED); > + print(string); > + color(EFI_LIGHTGRAY); > +} > + > +/** > + * Exit the boot services. > + * > + * The size of the memory map is determined. > + * Pool memory is allocated to copy the memory map. > + * The memory map is copied and the map key is obtained. > + * The map key is used to exit the boot services. > + */ > +efi_uintn_t exit_boot_services(void) > +{ > + efi_uintn_t map_size = 0; > + efi_uintn_t map_key; > + efi_uintn_t desc_size; > + u32 desc_version; > + efi_status_t ret; > + struct efi_mem_desc *memory_map; > + > + ret = boottime->get_memory_map(&map_size, NULL, &map_key, > &desc_size, > + &desc_version); > + if (ret != EFI_BUFFER_TOO_SMALL) { > + error(u"GetMemoryMap did not return > EFI_BUFFER_TOO_SMALL\r\n"); > + return ret; > + } > + /* Allocate extra space for newly allocated memory */ > + map_size += sizeof(struct efi_mem_desc); > + ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size, > + (void **)&memory_map); > + if (ret != EFI_SUCCESS) { > + error(u"AllocatePool did not return EFI_SUCCESS\r\n"); > + return ret; > + } > + ret = boottime->get_memory_map(&map_size, memory_map, &map_key, > + &desc_size, &desc_version); > + if (ret != EFI_SUCCESS) { > + error(u"GetMemoryMap did not return EFI_SUCCESS\r\n"); > + return ret; > + } > + ret = boottime->exit_boot_services(handle, map_key); > + if (ret != EFI_SUCCESS) { > + error(u"ExitBootServices did not return EFI_SUCCESS\r\n"); > + return ret; > + } > + return EFI_SUCCESS; > +} > + > +/** > + * ef
Re: [PATCH] [RFC] lib: efi_loader: don't delete invalid handles
Hello Heinirch, On Fri, 9 Sept 2022 at 08:55, Heinrich Schuchardt wrote: > > On 9/8/22 07:56, Heinrich Schuchardt wrote: > > On 9/7/22 23:10, Simon Glass wrote: > >> Hi Etienne, > >> > >> On Wed, 7 Sept 2022 at 02:20, Etienne Carriere > >> wrote: > >>> > >>> Changes efi_delete_handle() to not free EFI handles that are not related > >>> to EFI objects. > >>> > >>> This change tries to resolved an issue seen since U-Boot v2022.07 > >>> in which EFI ExitBootService attempts to release some EFI handles > >>> twice. > >>> > >>> The issue was seen booting a EFI shell that invokes 'connect -r' and > >>> then boots a Linux kernel. Execution of connect command makes EFI > >>> subsystem to bind a block device for each root block devices EFI > >>> handles. > >>> However these EFI device handles are already bound to a driver and we > >>> can have 2 registered devices relating to the same EFI handler. On > >>> ExitBootService, the loop removing the devices makes these EFI handles > >>> to be released twice which corrupts memory. > >>> > >>> This patch prevents the memory release operation caused by the issue but > >>> I don't think this patch is the right way to addresse the problem. Any > >>> help will be much appreciated. > >>> > >>> Signed-off-by: Etienne Carriere > >>> --- > >>> lib/efi_loader/efi_boottime.c | 8 +++- > >>> 1 file changed, 7 insertions(+), 1 deletion(-) > >> > >> +AKASHI Takahiro who has been working on resolving the mismatch > >> between driver model and the EFI implementation. We should be able to > >> attach EFI data structures to driver model devices, which may help > >> with this issue. > >> > >> What is the next step, there? > >> > >> Regards, > >> Simon > > > > One of the bugs is in efi_disk_delete_raw(). > > > > The only allowable way to delete a handle is to delete all protocols > > that are installed on it. But there are some caveats: > > > > * Protocols may not be removable because they have been opened by a > > driver or a child controller. > > * We should only remove those protocols that we installed. > > > > A correct DM-EFI interface implementation would do the following: > > > > * When creating a block device create a handle. > > * Install the EFI_BLOCK_IO_PROTOCOL on it. > > * Use ConnectController() to install all other protocols on it. Our > > implementation of the binding protocol then must open the > > EFI_BLOCK_IO_PROTOCOL with EFI_OPEN_PROTOCOL_BY_DRIVER. > > * When trying to remove the block device call > > UninstallProtocolInterface() for the EFI_BLOCK_IO_PROTOCOL. This invokes > > DisconnectController() for all drivers that have opened the protocol > > with EFI_OPEN_PROTOCOL_BY_DRIVER. Only if uninstalling the protocol > > interface succeeds remove the block device. > > > > To make this all work we have to change efi_bl_bind(). We have to > > differentiate here between a handle being passed in from outside > > (IF_EFI_LOADER) and a handle for a U-Boot device. We should be able to > > do so using the field dev in efi_object. If it is NULL, the handle is > > not for a U-Boot device. > > > > Further we need to implement the missing unbind function in the > > efi_block driver. > > > > The ConnectController() call has to be in efi_disk_probe(). > > The UninstallProtocolInterface() call has to be in efi_disk_remove(). > > > > Enough work for the next release cycle. > > > > Best regards > > > > Heinrich > > The connect -r command calls ConnectController() for all devices. > > The only instance of the EFI_DRIVER_BINDING_PROTOCOL that we supply is > for binding to the EFI_BLOCK_IO_PROTOCOL. > > In efi_uc_supported() we try to open the the EFI_BLOCK_IO_PROTOCOL with > EFI_OPEN_PROTOCOL_BY_DRIVER. This will return EFI_ALREADY_STARTED if our > driver is already bound to the handle. > > This part of the logic works fine and you can see when executing > 'connect -r' twice in the EFI Shell. > > EFI: Entry efi_uc_supported(1b241c40, 1b237b60, ) >EFI: Call: systab.boottime->open_protocol( controller_handle, > bp->ops->protocol, &interface, this->driver_binding_handle, > controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER) >EFI: 20 returned by systab.boottime->open_protocol( > co
Re: [PATCH 1/1] efi_driver: don't bind internal block devices
Hello Heinrich, On Fri, 9 Sept 2022 at 08:58, Heinrich Schuchardt wrote: > > UEFI block devices can either mirror U-Boot's internal devices or be > provided by an EFI application like iPXE. > > When ConnectController() is invoked for the EFI_BLOCK_IO_PROTOCOL > interface for such an application provided device we create a virtual > U-Boot block device of type "efi_blk". > > Currently we do not call ConnectController() when handles for U-Boot's > internal block devices are created. If an EFI application calls > ConnectController() for a handle relating to an internal block device, > we erroneously create an extra "efi_blk" block device. > > E.g. the UEFI shell has a command 'connect -r' which calls > ConnectController() for all handles. > > In the Supported() method of our EFI_DRIVER_BINDING_PROTOCOL return > EFI_ALREADY_STARTED when dealing with an U-Boot internal device. > > Reported-by: Etienne Carriere > Fixes: b406eb04c360 ("efi_loader: disk: a helper function to delete efi_disk > objects") > Signed-off-by: Heinrich Schuchardt > --- > lib/efi_driver/efi_uclass.c | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c > index b01ce89c84..d348960fc9 100644 > --- a/lib/efi_driver/efi_uclass.c > +++ b/lib/efi_driver/efi_uclass.c > @@ -71,6 +71,11 @@ static efi_status_t EFIAPI efi_uc_supported( > EFI_ENTRY("%p, %p, %ls", this, controller_handle, > efi_dp_str(remaining_device_path)); > > + if (controller_handle->dev) { > + ret = EFI_ALREADY_STARTED; > + goto out; > + } > + > ret = EFI_CALL(systab.boottime->open_protocol( > controller_handle, bp->ops->protocol, > &interface, this->driver_binding_handle, > -- > 2.30.2 > Reviewed-by: Etienne Carriere Tested-by: Etienne Carriere Thanks for the fix and commitment. Best regards, Etienne
Re: [PATCH v4] tee: optee: rework TA bus scanning code
Hello Patrick and all, On Mon, 19 Sept 2022 at 16:49, Patrick DELAUNAY wrote: > > > Hi Simon, > > On 9/12/22 20:31, Simon Glass wrote: > > Hi Ilias, > > > > On Wed, 7 Sept 2022 at 15:32, Ilias Apalodimas > > wrote: > >> Hi Simon, > >> > >> On Thu, 8 Sept 2022 at 00:11, Simon Glass wrote: > >>> Hi Ilias, > >>> > >>> On Tue, 6 Sept 2022 at 15:23, Ilias Apalodimas > >>> wrote: > >>>> Hi Simon, > >>>> > >>>> On Tue, Sep 06, 2022 at 03:18:28PM -0600, Simon Glass wrote: > >>>>> Hi, > >>>>> > >>>>> On Tue, 6 Sept 2022 at 03:37, Ilias Apalodimas > >>>>> wrote: > >>>>>> Late versions of OP-TEE support a pseudo bus. TAs that behave as > >>>>>> hardware blocks (e.g TPM, RNG etc) present themselves on a bus > >>>>>> whichwe can > >>>>>> scan. Unfortunately U-Boot doesn't support that yet. It's worth > >>>>>> noting > >>>>>> that we already have a workaround for RNG. The details are in > >>>>>> commit 70812bb83da6 ("tee: optee: bind rng optee driver") > >>>>>> > >>>>>> So let's add a list of devices based on U-Boot Kconfig options > >>>>>> that we will > >>>>>> scan until we properly implement the tee-bus functionality. > >>>>>> > >>>>>> While at it change the behaviour of the tee core itself wrt to device > >>>>>> binding. If some device binding fails, print a warning instead of > >>>>>> disabling OP-TEE. > >>>>>> > >>>>>> Signed-off-by: Ilias Apalodimas > >>>>>> Reviewed-by: Jens Wiklander > >>>>>> Reviewed-by: Etienne Carriere > >>>>>> --- > >>>>>> Changes since v3: > >>>>>> - Use NULL instead of a child ptr on device_bind_driver(), since > >>>>>> it's not > >>>>>> really needed > >>>>>> - Changed the style of the optee_bus_probe[] definition to > >>>>>> {.drv_name = xxx, .dev_name = yyy } > >>>>>> > >>>>>> Changes since v2: > >>>>>> - Fixed typo on driver name ftpm-tee -> ftpm_tee > >>>>>> > >>>>>> Changes since v1: > >>>>>> - remove a macro and use ARRAY_SIZE directly > >>>>>> drivers/tee/optee/core.c | 24 +++- > >>>>>> 1 file changed, 19 insertions(+), 5 deletions(-) > >>>>>> > >>>>>> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > >>>>>> index a89d62aaf0b3..c201a4635e6b 100644 > >>>>>> --- a/drivers/tee/optee/core.c > >>>>>> +++ b/drivers/tee/optee/core.c > >>>>>> @@ -31,6 +31,18 @@ struct optee_pdata { > >>>>>> optee_invoke_fn *invoke_fn; > >>>>>> }; > >>>>>> > >>>>>> +static const struct { > >>>>>> + const char *drv_name; > >>>>>> + const char *dev_name; > >>>>>> +} optee_bus_probe[] = { > >>>>>> +#ifdef CONFIG_RNG_OPTEE > >>>>>> + { .drv_name = "optee-rng", .dev_name = "optee-rng" }, > >>>>>> +#endif > >>>>>> +#ifdef CONFIG_TPM2_FTPM_TEE > >>>>>> + { .drv_name = "ftpm_tee", .dev_name = "ftpm_tee" }, > >>>>>> +#endif > >>>>>> +}; > >>>>>> + > >>>>>> struct rpc_param { > >>>>>> u32 a0; > >>>>>> u32 a1; > >>>>>> @@ -642,8 +654,7 @@ static int optee_probe(struct udevice *dev) > >>>>>> { > >>>>>> struct optee_pdata *pdata = dev_get_plat(dev); > >>>>>> u32 sec_caps; > >>>>>> - struct udevice *child; > >>>>>> - int ret; > >>>>>> + int ret, i; > >>>>>> > >>>>>> if (!is_optee_api(pdata->invoke_fn)) { > >>>>>> dev_err(dev, "OP-TEE api uid mismatch\n"); > >>>>>> @@ -672,10 +683,13 @@ static int optee_probe(struct udevice *dev) > >>
Re: [PATCH v4] tee: optee: rework TA bus scanning code
On Thu, 22 Sept 2022 at 13:27, Simon Glass wrote: > > Hi Etienne, > > On Thu, 22 Sept 2022 at 10:52, Etienne Carriere > wrote: > > > > Hello Patrick and all, > > > > On Mon, 19 Sept 2022 at 16:49, Patrick DELAUNAY > > wrote: > > > > > > > > > Hi Simon, > > > > > > On 9/12/22 20:31, Simon Glass wrote: > > > > Hi Ilias, > > > > > > > > On Wed, 7 Sept 2022 at 15:32, Ilias Apalodimas > > > > wrote: > > > >> Hi Simon, > > > >> > > > >> On Thu, 8 Sept 2022 at 00:11, Simon Glass wrote: > > > >>> Hi Ilias, > > > >>> > > > >>> On Tue, 6 Sept 2022 at 15:23, Ilias Apalodimas > > > >>> wrote: > > > >>>> Hi Simon, > > > >>>> > > > >>>> On Tue, Sep 06, 2022 at 03:18:28PM -0600, Simon Glass wrote: > > > >>>>> Hi, > > > >>>>> > > > >>>>> On Tue, 6 Sept 2022 at 03:37, Ilias Apalodimas > > > >>>>> wrote: > > > >>>>>> Late versions of OP-TEE support a pseudo bus. TAs that behave as > > > >>>>>> hardware blocks (e.g TPM, RNG etc) present themselves on a bus > > > >>>>>> whichwe can > > > >>>>>> scan. Unfortunately U-Boot doesn't support that yet. It's worth > > > >>>>>> noting > > > >>>>>> that we already have a workaround for RNG. The details are in > > > >>>>>> commit 70812bb83da6 ("tee: optee: bind rng optee driver") > > > >>>>>> > > > >>>>>> So let's add a list of devices based on U-Boot Kconfig options > > > >>>>>> that we will > > > >>>>>> scan until we properly implement the tee-bus functionality. > > > >>>>>> > > > >>>>>> While at it change the behaviour of the tee core itself wrt to > > > >>>>>> device > > > >>>>>> binding. If some device binding fails, print a warning instead of > > > >>>>>> disabling OP-TEE. > > > >>>>>> > > > >>>>>> Signed-off-by: Ilias Apalodimas > > > >>>>>> Reviewed-by: Jens Wiklander > > > >>>>>> Reviewed-by: Etienne Carriere > > > >>>>>> --- > > > >>>>>> Changes since v3: > > > >>>>>> - Use NULL instead of a child ptr on device_bind_driver(), since > > > >>>>>> it's not > > > >>>>>> really needed > > > >>>>>> - Changed the style of the optee_bus_probe[] definition to > > > >>>>>> {.drv_name = xxx, .dev_name = yyy } > > > >>>>>> > > > >>>>>> Changes since v2: > > > >>>>>> - Fixed typo on driver name ftpm-tee -> ftpm_tee > > > >>>>>> > > > >>>>>> Changes since v1: > > > >>>>>> - remove a macro and use ARRAY_SIZE directly > > > >>>>>> drivers/tee/optee/core.c | 24 +++- > > > >>>>>> 1 file changed, 19 insertions(+), 5 deletions(-) > > > >>>>>> > > > >>>>>> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > > > >>>>>> index a89d62aaf0b3..c201a4635e6b 100644 > > > >>>>>> --- a/drivers/tee/optee/core.c > > > >>>>>> +++ b/drivers/tee/optee/core.c > > > >>>>>> @@ -31,6 +31,18 @@ struct optee_pdata { > > > >>>>>> optee_invoke_fn *invoke_fn; > > > >>>>>> }; > > > >>>>>> > > > >>>>>> +static const struct { > > > >>>>>> + const char *drv_name; > > > >>>>>> + const char *dev_name; > > > >>>>>> +} optee_bus_probe[] = { > > > >>>>>> +#ifdef CONFIG_RNG_OPTEE > > > >>>>>> + { .drv_name = "optee-rng", .dev_name = "optee-rng" }, > > > >>>>>> +#endif > > > >>>>>> +#ifdef CONFIG_TPM2_FTPM_TEE > > > >>>>>
Re: [PATCH v4] tee: optee: rework TA bus scanning code
Hello Sumit, On Thu, 22 Sept 2022 at 12:15, Sumit Garg wrote: > > On Thu, 22 Sept 2022 at 14:22, Etienne Carriere > wrote: > > > > Hello Patrick and all, > > > > On Mon, 19 Sept 2022 at 16:49, Patrick DELAUNAY > > wrote: > > > > > > > > > Hi Simon, > > > > > > On 9/12/22 20:31, Simon Glass wrote: > > > > Hi Ilias, > > > > > > > > On Wed, 7 Sept 2022 at 15:32, Ilias Apalodimas > > > > wrote: > > > >> Hi Simon, > > > >> > > > >> On Thu, 8 Sept 2022 at 00:11, Simon Glass wrote: > > > >>> Hi Ilias, > > > >>> > > > >>> On Tue, 6 Sept 2022 at 15:23, Ilias Apalodimas > > > >>> wrote: > > > >>>> Hi Simon, > > > >>>> > > > >>>> On Tue, Sep 06, 2022 at 03:18:28PM -0600, Simon Glass wrote: > > > >>>>> Hi, > > > >>>>> > > > >>>>> On Tue, 6 Sept 2022 at 03:37, Ilias Apalodimas > > > >>>>> wrote: > > > >>>>>> Late versions of OP-TEE support a pseudo bus. TAs that behave as > > > >>>>>> hardware blocks (e.g TPM, RNG etc) present themselves on a bus > > > >>>>>> whichwe can > > > >>>>>> scan. Unfortunately U-Boot doesn't support that yet. It's worth > > > >>>>>> noting > > > >>>>>> that we already have a workaround for RNG. The details are in > > > >>>>>> commit 70812bb83da6 ("tee: optee: bind rng optee driver") > > > >>>>>> > > > >>>>>> So let's add a list of devices based on U-Boot Kconfig options > > > >>>>>> that we will > > > >>>>>> scan until we properly implement the tee-bus functionality. > > > >>>>>> > > > >>>>>> While at it change the behaviour of the tee core itself wrt to > > > >>>>>> device > > > >>>>>> binding. If some device binding fails, print a warning instead of > > > >>>>>> disabling OP-TEE. > > > >>>>>> > > > >>>>>> Signed-off-by: Ilias Apalodimas > > > >>>>>> Reviewed-by: Jens Wiklander > > > >>>>>> Reviewed-by: Etienne Carriere > > > >>>>>> --- > > > >>>>>> Changes since v3: > > > >>>>>> - Use NULL instead of a child ptr on device_bind_driver(), since > > > >>>>>> it's not > > > >>>>>> really needed > > > >>>>>> - Changed the style of the optee_bus_probe[] definition to > > > >>>>>> {.drv_name = xxx, .dev_name = yyy } > > > >>>>>> > > > >>>>>> Changes since v2: > > > >>>>>> - Fixed typo on driver name ftpm-tee -> ftpm_tee > > > >>>>>> > > > >>>>>> Changes since v1: > > > >>>>>> - remove a macro and use ARRAY_SIZE directly > > > >>>>>> drivers/tee/optee/core.c | 24 +++- > > > >>>>>> 1 file changed, 19 insertions(+), 5 deletions(-) > > > >>>>>> > > > >>>>>> diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > > > >>>>>> index a89d62aaf0b3..c201a4635e6b 100644 > > > >>>>>> --- a/drivers/tee/optee/core.c > > > >>>>>> +++ b/drivers/tee/optee/core.c > > > >>>>>> @@ -31,6 +31,18 @@ struct optee_pdata { > > > >>>>>> optee_invoke_fn *invoke_fn; > > > >>>>>> }; > > > >>>>>> > > > >>>>>> +static const struct { > > > >>>>>> + const char *drv_name; > > > >>>>>> + const char *dev_name; > > > >>>>>> +} optee_bus_probe[] = { > > > >>>>>> +#ifdef CONFIG_RNG_OPTEE > > > >>>>>> + { .drv_name = "optee-rng", .dev_name = "optee-rng" }, > > > >>>>>> +#endif > > > >>>>>> +#ifdef CONFIG_TPM2_FTPM_TEE > > > >>>>>> + { .dr
Re: [PATCH v10 03/15] FWU: Add FWU metadata access driver for GPT partitioned block devices
Hello Sughosh and all, On Mon, 26 Sept 2022 at 10:46, Sughosh Ganu wrote: > > hi Ilias, > > On Thu, 22 Sept 2022 at 14:16, Ilias Apalodimas > wrote: > > > > Hi Sughosh > > > > On Thu, Sep 15, 2022 at 01:44:39PM +0530, Sughosh Ganu wrote: > > > In the FWU Multi Bank Update feature, the information about the > > > updatable images is stored as part of the metadata, on a separate > > > partition. Add a driver for reading from and writing to the metadata > > > when the updatable images and the metadata are stored on a block > > > device which is formatted with GPT based partition scheme. > > > > > > Signed-off-by: Sughosh Ganu > > > Reviewed-by: Patrick Delaunay > > > Reviewed-by: Etienne Carriere > > > --- > > > Changes since V9: > > > * s/formated/formatted in the commit message > > > * Add a '\n' character in the log message > > > > > > drivers/fwu-mdata/Kconfig | 16 ++ > > > drivers/fwu-mdata/Makefile | 8 + > > > drivers/fwu-mdata/gpt_blk.c | 378 > > > include/fwu.h | 4 + > > > 4 files changed, 406 insertions(+) > > > create mode 100644 drivers/fwu-mdata/Kconfig > > > create mode 100644 drivers/fwu-mdata/Makefile > > > create mode 100644 drivers/fwu-mdata/gpt_blk.c > > > > > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > > > new file mode 100644 > > > index 00..7322da48b1 > > > --- /dev/null > > > +++ b/drivers/fwu-mdata/Kconfig > > > @@ -0,0 +1,16 @@ > > > +config FWU_MDATA > > > + bool "Driver support for accessing FWU Metadata" > > > + depends on DM > > > + help > > > + Enable support for accessing FWU Metadata partitions. The > > > + FWU Metadata partitions reside on the same storage device > > > + which contains the other FWU updatable firmware images. > > > + > > > +config FWU_MDATA_GPT_BLK > > > + bool "FWU Metadata access for GPT partitioned Block devices" > > > + select PARTITION_TYPE_GUID > > > + select PARTITION_UUIDS > > > + depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION > > > + help > > > + Enable support for accessing FWU Metadata on GPT partitioned > > > + block devices. By the way, drop HAVE_BLOCK_DEVICE that is no more needed here. See https://source.denx.de/u-boot/u-boot/-/commit/7f8967c2b82f9917987b69fbf43f8f591f3a8516 > > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > > > new file mode 100644 > > > index 00..3fee64c10c > > > --- /dev/null > > > +++ b/drivers/fwu-mdata/Makefile > > > @@ -0,0 +1,8 @@ > > > +# SPDX-License-Identifier: GPL-2.0-or-later > > > +# > > > +# Copyright (c) 2022, Linaro Limited > > > +# > > > + > > > + > > > +obj-$(CONFIG_FWU_MDATA) += fwu-mdata-uclass.o > > > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += gpt_blk.o > > > diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c > > > new file mode 100644 > > > index 00..df115575e0 > > > --- /dev/null > > > +++ b/drivers/fwu-mdata/gpt_blk.c > > > @@ -0,0 +1,378 @@ > > > +// SPDX-License-Identifier: GPL-2.0-or-later > > > +/* > > > + * Copyright (c) 2022, Linaro Limited > > > + */ > > > + > > > +#define LOG_CATEGORY UCLASS_FWU_MDATA > > > + > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > +#include > > > + > > > +#include > > > +#include > > > +#include > > > + > > > +#define PRIMARY_PART BIT(0) > > > +#define SECONDARY_PART BIT(1) > > > +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) > > > + > > > +#define MDATA_READ BIT(0) > > > +#define MDATA_WRITE BIT(1) > > > + > > > +static int gpt_get_mdata_partitions(struct blk_desc *desc, > > > + uint *primary_mpart, > > > + uint *secondary_mpart) > > > +{ > > > + int i, ret; > > > + u32 mdata_parts; > > > + efi_guid_t part_type_guid; > > > + s
Re: [PATCH v10 07/15] FWU: STM32MP1: Add support to read boot index from backup register
On Thu, 15 Sept 2022 at 10:15, Sughosh Ganu wrote: > > The FWU Multi Bank Update feature allows the platform to boot the > firmware images from one of the partitions(banks). The first stage > bootloader(fsbl) passes the value of the boot index, i.e. the bank > from which the firmware images were booted from to U-Boot. On the > STM32MP157C-DK2 board, this value is passed through one of the SoC's > backup register. Add a function to read the boot index value from the > backup register. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Acked-by: Ilias Apalodimas > --- > Changes since V9: > * Change the fwu_plat_get_bootidx() function to take an uint * as the > function parameter instead of the void * as suggested by Etienne. > > arch/arm/mach-stm32mp/include/mach/stm32.h | 5 + > board/st/stm32mp1/stm32mp1.c | 23 ++ > include/fwu.h | 12 +++ > 3 files changed, 40 insertions(+) > > diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h > b/arch/arm/mach-stm32mp/include/mach/stm32.h > index c70375a723..c85ae6a34e 100644 > --- a/arch/arm/mach-stm32mp/include/mach/stm32.h > +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h > @@ -112,11 +112,16 @@ enum boot_device { > #ifdef CONFIG_STM32MP15x > #define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4) > #define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5) > +#define TAMP_FWU_BOOT_INFO_REG TAMP_BACKUP_REGISTER(10) > #define TAMP_COPRO_RSC_TBL_ADDRESS TAMP_BACKUP_REGISTER(17) > #define TAMP_COPRO_STATE TAMP_BACKUP_REGISTER(18) > #define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20) > #define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21) > > +#define TAMP_FWU_BOOT_IDX_MASK GENMASK(3, 0) > + > +#define TAMP_FWU_BOOT_IDX_OFFSET 0 > + > #define TAMP_COPRO_STATE_OFF 0 > #define TAMP_COPRO_STATE_INIT 1 > #define TAMP_COPRO_STATE_CRUN 2 > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > index 6562bcf95b..54b9535405 100644 > --- a/board/st/stm32mp1/stm32mp1.c > +++ b/board/st/stm32mp1/stm32mp1.c > @@ -960,3 +960,26 @@ static void board_copro_image_process(ulong fw_image, > size_t fw_size) > } > > U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process); > + > +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) > + > +#include > + > +/** > + * fwu_plat_get_bootidx() - Get the value of the boot index > + * @boot_idx: Boot index value > + * > + * Get the value of the bank(partition) from which the platform > + * has booted. This value is passed to U-Boot from the earlier > + * stage bootloader which loads and boots all the relevant > + * firmware images > + * > + */ > +void fwu_plat_get_bootidx(uint *boot_idx) > +{ > + u32 *bootidx = boot_idx; > + > + *bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >> > + TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; > +} I may be nitpicking but despite this is fine in this source file build only for 32bit, I think the cast is not that clean. Would prefer: void fwu_plat_get_bootidx(uint *boot_idx) { *boot_idx = (readl(TAMP_FWU_BOOT_INFO_REG) >> TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK; } br, etienne > +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ > diff --git a/include/fwu.h b/include/fwu.h > index 3ff37c628b..484289ed4f 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -244,4 +244,16 @@ int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t > *image_guid, > * > */ > int fwu_plat_get_update_index(uint *update_idx); > + > +/** > + * fwu_plat_get_bootidx() - Get the value of the boot index > + * @boot_idx: Boot index value > + * > + * Get the value of the bank(partition) from which the platform > + * has booted. This value is passed to U-Boot from the earlier > + * stage bootloader which loads and boots all the relevant > + * firmware images > + * > + */ > +void fwu_plat_get_bootidx(uint *boot_idx); > #endif /* _FWU_H_ */ > -- > 2.34.1 >
Re: [PATCH v10 15/15] FWU: doc: Add documentation for the FWU feature
Hello Sughosh, Thanks for the documentation. See comments on few typos found (with help of my editor) and suggestions. Best regards, Etienne On Thu, 15 Sept 2022 at 10:16, Sughosh Ganu wrote: > > Add documentattion for the FWU Multi Bank Update feature. The document s/documentattion/documentation/ > describes the steps needed for setting up the platform for the > feature, as well as steps for enabling the feature on the platform. > > Signed-off-by: Sughosh Ganu > --- > Changes since V9: None > > doc/develop/uefi/fwu_updates.rst | 165 +++ > doc/develop/uefi/index.rst | 1 + > doc/develop/uefi/uefi.rst| 2 + > 3 files changed, 168 insertions(+) > create mode 100644 doc/develop/uefi/fwu_updates.rst > > diff --git a/doc/develop/uefi/fwu_updates.rst > b/doc/develop/uefi/fwu_updates.rst > new file mode 100644 > index 00..fad3fbb3a8 > --- /dev/null > +++ b/doc/develop/uefi/fwu_updates.rst > @@ -0,0 +1,165 @@ > +.. SPDX-License-Identifier: GPL-2.0+ > +.. Copyright (c) 2022 Linaro Limited > + > +FWU Multi Bank Updates in U-Boot > + > + > +The FWU Multi Bank Update feature implements the firmware update > +mechanism described in the PSA Firmware Update for A-profile Arm > +Architecture specification [1]. Certain aspects of the Dependable > +Boot specification [2] are also implemented. The feature provides a > +mechanism to have multiple banks of updatable firmware images and for > +updating the firmware images on the non-booted bank. On a successful > +update, the platform boots from the updated bank on subsequent > +boot. The UEFI capsule-on-disk update feature is used for performing > +the actual updates of the updatable firmware images. > + > +The bookkeeping of the updatable images is done through a structure > +called metadata. Currently, the FWU metadata supports identification > +of images based on image GUIDs stored on a GPT partitioned storage > +media. There are plans to extend the metadata structure for non GPT > +partitioned devices as well. > + > +Accessing the FWU metadata is done through generic API's which are > +defined in a driver which complies with the U-Boot's driver model. A > +new uclass UCLASS_FWU_MDATA has been added for accessing the FWU > +metadata. Individual drivers can be added based on the type of storage > +media, and it's partitioning method. Details of the storage device s/it's/its/ > +containing the FWU metadata partitions are specified through a U-Boot > +specific device tree property `fwu-mdata-store`. Please refer to > +U-Boot `doc `__ > +for the device tree bindings. > + > +Enabling the FWU Multi Bank Update feature > +-- > + > +The feature can be enabled by specifying the following configs:: > + > +CONFIG_EFI_CAPSULE_ON_DISK=y > +CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y > +CONFIG_EFI_CAPSULE_FIRMWARE=y CONFIG_EFI_CAPSULE_FIRMWARE is not needed. Selected by the above. > +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y > + > +CONFIG_FWU_MULTI_BANK_UPDATE=y > +CONFIG_CMD_FWU_METADATA=y > +CONFIG_DM_FWU_MDATA=y Note also in efi_setup.c, CONFIG_FWU_MULTI_BANK_UPDATE enforces capsules are not checked at 1st EFI command. This means we need CONFIG_EFI_CAPSULE_ON_DISK_EARLY=y, if I'm right. > +CONFIG_FWU_MDATA_GPT_BLK=y > +CONFIG_FWU_NUM_BANKS= > +CONFIG_FWU_NUM_IMAGES_PER_BANK= > + > +in the .config file > + > +The first group of configuration settings enable the UEFI > +capsule-on-disk update functionality. The second group of configs > +enable the FWU Multi Bank Update functionality. Please refer to the > +section :ref:`uefi_capsule_update_ref` for more details on generation > +of the UEFI capsule. > + > +Setting up the device for GPT partitioned storage > +- > + > +Before enabling the functionality in U-Boot, a GPT partitioned storage > +device is required. Assuming a GPT partitioned storage device, the > +storage media needs to be partitioned with the correct number of > +partitions, given the number of banks and number of images per bank > +that the platform is going to support. Each updatable firmware image > +will be stored on an separate partition. In addition, the two copies s/an/a/ > +of the FWU metadata will be stored on two separate partitions. > + > +As an example, a platform supporting two banks with each bank > +containing three images would need to have 2 * 3 = 6 partitions plus > +the two metadata partitions, or 8 partitions. In addition the storage > +media can have additional partitions of non-updatable images, like the > +EFI System Partition(ESP), a partition for the root file system > +etc. An example list of images on the storage medium would be > + > +* FWU metadata 1 > +* U-Boot 1 > +* OP-TEE 1 > +* FWU metadata 2 > +* OP-TEE 2 > +* U-Boot 2 > +* ESP > +* rootfs > + > +When generating the partitions, a few aspects need to be taken care > +of. E
Re: [PATCH v10 10/15] FWU: Add support for the FWU Multi Bank Update feature
Hello Jassi, Sughosh and all, On Wed, 28 Sept 2022 at 08:23, Sughosh Ganu wrote: > > On Tue, 27 Sept 2022 at 22:19, Jassi Brar wrote: > > > > On Tue, Sep 27, 2022 at 2:22 AM Sughosh Ganu > > wrote: > > > > > > On Mon, 26 Sept 2022 at 20:24, Jassi Brar > > > wrote: > > > > > > > > On Mon, Sep 26, 2022 at 4:01 AM Sughosh Ganu > > > > wrote: > > > > > On Mon, 26 Sept 2022 at 08:25, Jassi Brar > > > > > wrote: > > > > > > > > > > . > > > > > > > > > > > > > > +static __maybe_unused efi_status_t fwu_post_update_process(bool > > > > > > > fw_accept_os) > > > > > > > +{ > > > > > > > + int status; > > > > > > > + u32 update_index; > > > > > > > + efi_status_t ret; > > > > > > > + > > > > > > > + status = fwu_plat_get_update_index(&update_index); > > > > > > > + if (status < 0) { > > > > > > > + log_err("Failed to get the FWU update_index > > > > > > > value\n"); > > > > > > > + return EFI_DEVICE_ERROR; > > > > > > > + } > > > > > > > + > > > > > > > + /* > > > > > > > +* All the capsules have been updated successfully, > > > > > > > +* update the FWU metadata. > > > > > > > +*/ > > > > > > > + log_debug("Update Complete. Now updating active_index to > > > > > > > %u\n", > > > > > > > + update_index); > > > > > > > + status = fwu_update_active_index(update_index); > > > > > > > > > > > > > Do we want to check if all images in the bank are updated via > > > > > > capsules > > > > > > before switching the bank? > > > > > > > > > > This function does get called only when the update status for every > > > > > capsule is a success. Even if one of the capsules does not get > > > > > updated, the active index will not get updated. > > > > > > > > > but we don't check if the capsule for each image in the bank is > > > > provided for update. > > > > > > Yes, we have had this discussion earlier. Neither the FWU spec, nor > > > the capsule update spec in UEFI puts that restriction that all images > > > on the platform need to be updated. If a user wants to ensure such a > > > behaviour, they may choose some kind of image packaging like FIP or > > > FIT which would mean that all the images on the platform are being > > > updated. But this is not something to be ensured by the FWU update > > > code. > > > > > > > > > > > > > > > > > > > A developer will make sure all images are provided in one go, so > > > > > > that > > > > > > the switch is successful. > > > > > > But a malicious user may force some old vulnerable image back into > > > > > > use > > > > > > by updating all but that image. > > > > > > > > > > That I believe is to be handled through a combination of implementing > > > > > a rollback protection mechanism, along with capsule authentication. > > > > > These are separate to the implementation of the multi bank updates > > > > > that these patches are aiming for. > > > > > > > > > This sounds like : we don't worry about buffer-overflow > > > > vulnerabilities because the system will be secured and hardened by > > > > other mechanisms. > > > > > > Not sure how this is related. The aim of the FWU spec is for providing > > > a means for a platform to maintain multiple partitions of images and > > > to specify the metadata structure for the bookkeeping of the different > > > partitions and images on those partitions. If we need a more secure > > > and hardened system, we do have the Dependable Boot spec, which is > > > talking precisely about these things. Those are indeed separate > > > features or aspects from what the FWU spec is talking about. And this > > > patchset is implementing the FWU spec. > > > > > > > I am out of ways to explain. Best of luck. > > Let me try one last time. If you still do not agree with what I say, > let us agree to disagree :) > > You mentioned earlier that a malicious user may force some old > vulnerable image back into use by updating all but that image. Now a > few points to consider here. The FWU spec recommends that platforms > follow the Platform Security Boot Guide [1] which specifies the > trusted boot flow for platforms where the firmware images being booted > on the platform, including the NWd bootloader(BL33 in tf-a jargon) are > verified before getting booted. Let me add that in tf-a we can bind booted images (actually booted certificates) version id to a platform non-volatile monotonic counter. This adds rollback protection on booted images upgrades. Enabling firmware update, we need this rollback protection to prevent cases like you mentioned above: >>> But a malicious user may force some old vulnerable image back into use >>> by updating all but that image. When the system boots with accepted images (referring to fwu-mdata regular/trial state), the platform monotonic counter is updated against booted image version number if needed, preventing older images to be booted when an accepted image has been deployed. @Jassi, does t
[PATCH] tee: optee: discover services dependent on tee-supplicant
This change makes OP-TEE to enumerate both standalone services and the services depending on tee-supplicant support in U-Boot. This change also drivers for this later to be bind. It is assumed that one implementing an OP-TEE device driver has all expected tee-supplicant services support in U-Boot. Signed-off-by: Etienne Carriere --- drivers/tee/optee/core.c | 32 +++- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 9240277579..7da35f2eda 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -102,13 +102,14 @@ static int bind_service_list(struct udevice *dev, struct tee_shm *service_list, return 0; } -static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t *shm_size, u32 tee_sess) +static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t *shm_size, u32 tee_sess, + unsigned int pta_cmd) { struct tee_invoke_arg arg = { }; struct tee_param param = { }; int ret = 0; - arg.func = PTA_CMD_GET_DEVICES; + arg.func = pta_cmd; arg.session = tee_sess; /* Fill invoke cmd params */ @@ -118,7 +119,7 @@ static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t *shm ret = tee_invoke_func(dev, &arg, 1, ¶m); if (ret || (arg.ret && arg.ret != TEE_ERROR_SHORT_BUFFER)) { - dev_err(dev, "PTA_CMD_GET_DEVICES invoke function err: 0x%x\n", arg.ret); + dev_err(dev, "Enumeration command 0x%x failed: 0x%x\n", pta_cmd, arg.ret); return -EINVAL; } @@ -127,12 +128,13 @@ static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t *shm return 0; } -static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t *count, u32 tee_sess) +static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t *count, u32 tee_sess, +unsigned int pta_cmd) { size_t shm_size = 0; int ret; - ret = __enum_services(dev, NULL, &shm_size, tee_sess); + ret = __enum_services(dev, NULL, &shm_size, tee_sess, pta_cmd); if (ret) return ret; @@ -142,7 +144,7 @@ static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t *coun return ret; } - ret = __enum_services(dev, *shm, &shm_size, tee_sess); + ret = __enum_services(dev, *shm, &shm_size, tee_sess, pta_cmd); if (!ret) *count = shm_size / sizeof(struct tee_optee_ta_uuid); @@ -174,20 +176,32 @@ static int bind_service_drivers(struct udevice *dev) struct tee_shm *service_list = NULL; size_t service_count; u32 tee_sess; - int ret; + int ret, ret2; ret = open_enum_session(dev, &tee_sess); if (ret) return ret; - ret = enum_services(dev, &service_list, &service_count, tee_sess); + ret = enum_services(dev, &service_list, &service_count, tee_sess, + PTA_CMD_GET_DEVICES); if (!ret) ret = bind_service_list(dev, service_list, service_count); tee_shm_free(service_list); + + ret2 = enum_services(dev, &service_list, &service_count, tee_sess, +PTA_CMD_GET_DEVICES_SUPP); + if (!ret2) + ret2 = bind_service_list(dev, service_list, service_count); + + tee_shm_free(service_list); + tee_close_session(dev, tee_sess); - return ret; + if (ret) + return ret; + + return ret2; } /** -- 2.25.1
Re: [PATCH v4] tee: optee: rework TA bus scanning code
On Mon, 26 Sept 2022 at 09:06, Sumit Garg wrote: > > On Fri, 23 Sept 2022 at 11:16, Etienne Carriere > wrote: > > > > Hello Sumit, > > > > > > On Thu, 22 Sept 2022 at 12:15, Sumit Garg wrote: > > > > > > On Thu, 22 Sept 2022 at 14:22, Etienne Carriere > > > wrote: > > > > > > > > Hello Patrick and all, > > > > > > > > On Mon, 19 Sept 2022 at 16:49, Patrick DELAUNAY > > > > wrote: > > > > > > > > > > > > > > > Hi Simon, > > > > > > > > > > On 9/12/22 20:31, Simon Glass wrote: > > > > > > Hi Ilias, > > > > > > > > > > > > On Wed, 7 Sept 2022 at 15:32, Ilias Apalodimas > > > > > > wrote: > > > > > >> Hi Simon, > > > > > >> > > > > > >> On Thu, 8 Sept 2022 at 00:11, Simon Glass > > > > > >> wrote: > > > > > >>> Hi Ilias, > > > > > >>> > > > > > >>> On Tue, 6 Sept 2022 at 15:23, Ilias Apalodimas > > > > > >>> wrote: > > > > > >>>> Hi Simon, > > > > > >>>> > > > > > >>>> On Tue, Sep 06, 2022 at 03:18:28PM -0600, Simon Glass wrote: > > > > > >>>>> Hi, > > > > > >>>>> > > > > > >>>>> On Tue, 6 Sept 2022 at 03:37, Ilias Apalodimas > > > > > >>>>> wrote: > > > > > >>>>>> Late versions of OP-TEE support a pseudo bus. TAs that behave > > > > > >>>>>> as > > > > > >>>>>> hardware blocks (e.g TPM, RNG etc) present themselves on a bus > > > > > >>>>>> whichwe can > > > > > >>>>>> scan. Unfortunately U-Boot doesn't support that yet. It's worth > > > > > >>>>>> noting > > > > > >>>>>> that we already have a workaround for RNG. The details are in > > > > > >>>>>> commit 70812bb83da6 ("tee: optee: bind rng optee driver") > > > > > >>>>>> > > > > > >>>>>> So let's add a list of devices based on U-Boot Kconfig options > > > > > >>>>>> that we will > > > > > >>>>>> scan until we properly implement the tee-bus functionality. > > > > > >>>>>> > > > > > >>>>>> While at it change the behaviour of the tee core itself wrt to > > > > > >>>>>> device > > > > > >>>>>> binding. If some device binding fails, print a warning instead > > > > > >>>>>> of > > > > > >>>>>> disabling OP-TEE. > > > > > >>>>>> > > > > > >>>>>> Signed-off-by: Ilias Apalodimas > > > > > >>>>>> Reviewed-by: Jens Wiklander > > > > > >>>>>> Reviewed-by: Etienne Carriere > > > > > >>>>>> --- > > > > > >>>>>> Changes since v3: > > > > > >>>>>> - Use NULL instead of a child ptr on device_bind_driver(), > > > > > >>>>>> since > > > > > >>>>>> it's not > > > > > >>>>>> really needed > > > > > >>>>>> - Changed the style of the optee_bus_probe[] definition to > > > > > >>>>>> {.drv_name = xxx, .dev_name = yyy } > > > > > >>>>>> > > > > > >>>>>> Changes since v2: > > > > > >>>>>> - Fixed typo on driver name ftpm-tee -> ftpm_tee > > > > > >>>>>> > > > > > >>>>>> Changes since v1: > > > > > >>>>>> - remove a macro and use ARRAY_SIZE directly > > > > > >>>>>> drivers/tee/optee/core.c | 24 +++- > > > > > >>>>>> 1 file changed, 19 insertions(+), 5 deletions(-) > > > > > >>>>>> > > > > > >>>>>> diff --git a/drivers/tee/optee/core.c > > > > > >>&
Re: [PATCH] tee: optee: discover services dependent on tee-supplicant
Hello, For info, this patch currently applies on branch 'next'. It depends on commit 94ccfb78a4d6 ("drivers: tee: optee: discover OP-TEE services") not yet merged in 'master'. br, etienne On Wed, 28 Sept 2022 at 09:48, Etienne Carriere wrote: > > This change makes OP-TEE to enumerate both standalone services and > the services depending on tee-supplicant support in U-Boot. This > change also drivers for this later to be bind. It is assumed that > one implementing an OP-TEE device driver has all expected tee-supplicant > services support in U-Boot. > > Signed-off-by: Etienne Carriere > --- > drivers/tee/optee/core.c | 32 +++- > 1 file changed, 23 insertions(+), 9 deletions(-) > > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > index 9240277579..7da35f2eda 100644 > --- a/drivers/tee/optee/core.c > +++ b/drivers/tee/optee/core.c > @@ -102,13 +102,14 @@ static int bind_service_list(struct udevice *dev, > struct tee_shm *service_list, > return 0; > } > > -static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t > *shm_size, u32 tee_sess) > +static int __enum_services(struct udevice *dev, struct tee_shm *shm, size_t > *shm_size, u32 tee_sess, > + unsigned int pta_cmd) > { > struct tee_invoke_arg arg = { }; > struct tee_param param = { }; > int ret = 0; > > - arg.func = PTA_CMD_GET_DEVICES; > + arg.func = pta_cmd; > arg.session = tee_sess; > > /* Fill invoke cmd params */ > @@ -118,7 +119,7 @@ static int __enum_services(struct udevice *dev, struct > tee_shm *shm, size_t *shm > > ret = tee_invoke_func(dev, &arg, 1, ¶m); > if (ret || (arg.ret && arg.ret != TEE_ERROR_SHORT_BUFFER)) { > - dev_err(dev, "PTA_CMD_GET_DEVICES invoke function err: > 0x%x\n", arg.ret); > + dev_err(dev, "Enumeration command 0x%x failed: 0x%x\n", > pta_cmd, arg.ret); > return -EINVAL; > } > > @@ -127,12 +128,13 @@ static int __enum_services(struct udevice *dev, struct > tee_shm *shm, size_t *shm > return 0; > } > > -static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t > *count, u32 tee_sess) > +static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t > *count, u32 tee_sess, > +unsigned int pta_cmd) > { > size_t shm_size = 0; > int ret; > > - ret = __enum_services(dev, NULL, &shm_size, tee_sess); > + ret = __enum_services(dev, NULL, &shm_size, tee_sess, pta_cmd); > if (ret) > return ret; > > @@ -142,7 +144,7 @@ static int enum_services(struct udevice *dev, struct > tee_shm **shm, size_t *coun > return ret; > } > > - ret = __enum_services(dev, *shm, &shm_size, tee_sess); > + ret = __enum_services(dev, *shm, &shm_size, tee_sess, pta_cmd); > if (!ret) > *count = shm_size / sizeof(struct tee_optee_ta_uuid); > > @@ -174,20 +176,32 @@ static int bind_service_drivers(struct udevice *dev) > struct tee_shm *service_list = NULL; > size_t service_count; > u32 tee_sess; > - int ret; > + int ret, ret2; > > ret = open_enum_session(dev, &tee_sess); > if (ret) > return ret; > > - ret = enum_services(dev, &service_list, &service_count, tee_sess); > + ret = enum_services(dev, &service_list, &service_count, tee_sess, > + PTA_CMD_GET_DEVICES); > if (!ret) > ret = bind_service_list(dev, service_list, service_count); > > tee_shm_free(service_list); > + > + ret2 = enum_services(dev, &service_list, &service_count, tee_sess, > +PTA_CMD_GET_DEVICES_SUPP); > + if (!ret2) > + ret2 = bind_service_list(dev, service_list, service_count); > + > + tee_shm_free(service_list); > + > tee_close_session(dev, tee_sess); > > - return ret; > + if (ret) > + return ret; > + > + return ret2; > } > > /** > -- > 2.25.1 >
Re: [PATCH v11 05/15] stm32mp1: dk2: Add image information for capsule updates
On Wed, 28 Sept 2022 at 11:30, Sughosh Ganu wrote: > > Enabling capsule update functionality on the platform requires > populating information on the images that are to be updated using the > functionality. Do so for the DK2 board. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Reviewed-by: Ilias Apalodimas > --- Reviewed-by: Etienne Carriere with 1 comment: Could the commit header line be updated? the patch no more targets only DK2 among stm32mp1 platforms: - stm32mp1: dk2: Add image information for capsule updates +stm32mp1: Add image information for capsule updates Regards, Etienne > Changes since V10: > * Use image_index value of 1 for the FIP image as it is now relevant > > board/st/stm32mp1/stm32mp1.c | 18 ++ > include/configs/stm32mp15_common.h | 4 > 2 files changed, 22 insertions(+) > > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c > index 8c162b42a5..e43dab018f 100644 > --- a/board/st/stm32mp1/stm32mp1.c > +++ b/board/st/stm32mp1/stm32mp1.c > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -87,6 +88,16 @@ > #define USB_START_LOW_THRESHOLD_UV 123 > #define USB_START_HIGH_THRESHOLD_UV215 > > +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) > +struct efi_fw_image fw_images[1]; > + > +struct efi_capsule_update_info update_info = { > + .images = fw_images, > +}; > + > +u8 num_image_type_guids = ARRAY_SIZE(fw_images); > +#endif /* EFI_HAVE_CAPSULE_SUPPORT */ > + > int board_early_init_f(void) > { > /* nothing to do, only used in SPL */ > @@ -666,6 +677,13 @@ int board_init(void) > > setup_led(LEDST_ON); > > +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) > + efi_guid_t image_type_guid = STM32MP_FIP_IMAGE_GUID; > + > + guidcpy(&fw_images[0].image_type_id, &image_type_guid); > + fw_images[0].fw_name = u"STM32MP-FIP"; > + fw_images[0].image_index = 1; > +#endif > return 0; > } > > diff --git a/include/configs/stm32mp15_common.h > b/include/configs/stm32mp15_common.h > index c5412ffeb3..bb19dae945 100644 > --- a/include/configs/stm32mp15_common.h > +++ b/include/configs/stm32mp15_common.h > @@ -34,6 +34,10 @@ > #define CONFIG_SERVERIP 192.168.1.1 > #endif > > +#define STM32MP_FIP_IMAGE_GUID \ > + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \ > +0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) > + > > /*/ > #ifdef CONFIG_DISTRO_DEFAULTS > > /*/ > -- > 2.34.1 >
Re: [PATCH v11 02/15] FWU: Add FWU metadata structure and driver for accessing metadata
Hello Sughosh, On Wed, 28 Sept 2022 at 11:30, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > updatable images is stored as part of the metadata, which is stored on > a dedicated partition. Add the metadata structure, and a driver model > uclass which provides functions to access the metadata. These are > generic API's, and implementations can be added based on parameters > like how the metadata partition is accessed and what type of storage > device houses the metadata. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Reviewed-by: Etienne Carriere > --- > Changes since V10: > * s/fwu_update_active_index/fwu_set_active_index as per comment from > Jassi > * Change the argument type of fwu_set_active_index() to uint from u32 > as per comment from Jassi > * s/mdata_check/check_mdata as per comment from Jassi > * Fix the typo in the function comment of fwu_mdata_check() > > drivers/fwu-mdata/fwu-mdata-uclass.c | 107 > include/dm/uclass-id.h | 1 + > include/fwu.h| 211 > include/fwu_mdata.h | 67 + > lib/fwu_updates/fwu.c| 363 +++ > 5 files changed, 749 insertions(+) > create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c > create mode 100644 include/fwu.h > create mode 100644 include/fwu_mdata.h > create mode 100644 lib/fwu_updates/fwu.c > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > b/drivers/fwu-mdata/fwu-mdata-uclass.c > new file mode 100644 > index 00..4237b89520 > --- /dev/null > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > @@ -0,0 +1,107 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#define LOG_CATEGORY UCLASS_FWU_MDATA > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +/** > + * fwu_mdata_check() - Check if the FWU metadata is valid > + * @dev: FWU metadata device > + * > + * Validate both copies of the FWU metadata. If one of the copies > + * has gone bad, restore it from the other copy. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_mdata_check(struct udevice *dev) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->check_mdata) { > + log_debug("check_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->check_mdata(dev); > +} > + > +/** > + * fwu_get_mdata() - Get a FWU metadata copy > + * @dev: FWU metadata device > + * @mdata: Copy of the FWU metadata > + * > + * Get a valid copy of the FWU metadata. > + * > + * Note: This function is to be called first when modifying any fields > + * in the metadata. The sequence of calls to modify any field in the > + * metadata would be 1) fwu_get_mdata 2) Modify metadata, followed by > + * 3) fwu_update_mdata > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_get_mdata(struct udevice *dev, struct fwu_mdata *mdata) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->get_mdata) { > + log_debug("get_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->get_mdata(dev, mdata); > +} > + > +/** > + * fwu_update_mdata() - Update the FWU metadata > + * @dev: FWU metadata device > + * @mdata: Copy of the FWU metadata > + * > + * Update the FWU metadata structure by writing to the > + * FWU metadata partitions. > + * > + * Note: This function is not to be called directly to update the > + * metadata fields. The sequence of function calls should be > + * 1) fwu_get_mdata() 2) Modify the medata fields 3) fwu_update_mdata() > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_update_mdata(struct udevice *dev, struct fwu_mdata *mdata) > +{ > + void *buf; > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->update_mdata) { > + log_debug("get_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + /* > +* Calculate the crc32 for the updated FWU metadata > +* and put the updated value in the FWU metadata crc32 > +* field > +*/ > + buf = &mdata->version; > + mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32)); > + >
Re: [PATCH v11 03/15] FWU: Add FWU metadata access driver for GPT partitioned block devices
Hi Sughosh, My R-b tag still applies, with the 2 below comments addressed or not. Br, etienne On Wed, 28 Sept 2022 at 11:30, Sughosh Ganu wrote: > > In the FWU Multi Bank Update feature, the information about the > updatable images is stored as part of the metadata, on a separate > partition. Add a driver for reading from and writing to the metadata > when the updatable images and the metadata are stored on a block > device which is formatted with GPT based partition scheme. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Reviewed-by: Etienne Carriere > --- > Changes since V10: > * Use array for storing the metadata partition numbers as suggested by > Ilias > * Skip a couple of goto's in gpt_check_mdata_validity() as suggested > by Ilias > * Have the FWU_MDATA_GPT_BLK config symbol depend on FWU_MDATA and BLK > * Remove the comment in fwu_gpt_mdata_check() as it is already > mentioned in the corresponding API comment > > drivers/fwu-mdata/Kconfig | 16 ++ > drivers/fwu-mdata/Makefile | 8 + > drivers/fwu-mdata/gpt_blk.c | 356 > include/fwu.h | 4 + > 4 files changed, 384 insertions(+) > create mode 100644 drivers/fwu-mdata/Kconfig > create mode 100644 drivers/fwu-mdata/Makefile > create mode 100644 drivers/fwu-mdata/gpt_blk.c > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > new file mode 100644 > index 00..36c4479a59 > --- /dev/null > +++ b/drivers/fwu-mdata/Kconfig > @@ -0,0 +1,16 @@ > +config FWU_MDATA > + bool "Driver support for accessing FWU Metadata" > + depends on DM > + help > + Enable support for accessing FWU Metadata partitions. The > + FWU Metadata partitions reside on the same storage device > + which contains the other FWU updatable firmware images. > + > +config FWU_MDATA_GPT_BLK > + bool "FWU Metadata access for GPT partitioned Block devices" > + select PARTITION_TYPE_GUID > + select PARTITION_UUIDS > + depends on FWU_MDATA && BLK && EFI_PARTITION > + help > + Enable support for accessing FWU Metadata on GPT partitioned > + block devices. > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > new file mode 100644 > index 00..3fee64c10c > --- /dev/null > +++ b/drivers/fwu-mdata/Makefile > @@ -0,0 +1,8 @@ > +# SPDX-License-Identifier: GPL-2.0-or-later > +# > +# Copyright (c) 2022, Linaro Limited > +# > + > + > +obj-$(CONFIG_FWU_MDATA) += fwu-mdata-uclass.o > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += gpt_blk.o > diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c > new file mode 100644 > index 00..d20bb19d52 > --- /dev/null > +++ b/drivers/fwu-mdata/gpt_blk.c > @@ -0,0 +1,356 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#define LOG_CATEGORY UCLASS_FWU_MDATA > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#define PRIMARY_PART BIT(0) > +#define SECONDARY_PART BIT(1) > +#define BOTH_PARTS (PRIMARY_PART | SECONDARY_PART) > + > +#define MDATA_READ BIT(0) > +#define MDATA_WRITEBIT(1) > + > +static int gpt_get_mdata_partitions(struct blk_desc *desc, > + uint *mdata_parts) Maybe nitpicking but I think this should better explicit declare a 2 cell array argument: static int gpt_get_mdata_partitions(struct blk_desc *desc, uint mdata_parts[2]) > +{ > + int i, ret; > + u32 nparts; > + efi_guid_t part_type_guid; > + struct disk_partition info; > + const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID; > + > + nparts = 0; > + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { > + if (part_get_info(desc, i, &info)) > + continue; > + uuid_str_to_bin(info.type_guid, part_type_guid.b, > + UUID_STR_FORMAT_GUID); > + > + if (nparts < 2 && !guidcmp(&fwu_mdata_guid, &part_type_guid)) > { > + mdata_parts[nparts] = i; > + ++nparts; > + } > + } > + > + if (nparts != 2) { > + log_debug("Expect two copies of the FWU metadata instead of > %d\n", > + nparts); > + ret
Re: [PATCH v11 15/15] FWU: doc: Add documentation for the FWU feature
Hello Sughosh, 2 comments on the documentation. Otherwise it looks all good to me. Best regards, Etienne On Wed, 28 Sept 2022 at 11:31, Sughosh Ganu wrote: > > Add documentation for the FWU Multi Bank Update feature. The document > describes the steps needed for setting up the platform for the > feature, as well as steps for enabling the feature on the platform. > > Signed-off-by: Sughosh Ganu > --- > Changes since V10: > * Fix review comments suggested by Etienne > * Add a paragraph in the capsule update section to highlight the > difference in ImageIndex correlation with DFU alt num with FWU feature > enabled > > doc/develop/uefi/fwu_updates.rst | 173 +++ > doc/develop/uefi/index.rst | 1 + > doc/develop/uefi/uefi.rst| 10 ++ > 3 files changed, 184 insertions(+) > create mode 100644 doc/develop/uefi/fwu_updates.rst > > diff --git a/doc/develop/uefi/fwu_updates.rst > b/doc/develop/uefi/fwu_updates.rst > new file mode 100644 > index 00..292feceb9a > --- /dev/null > +++ b/doc/develop/uefi/fwu_updates.rst > @@ -0,0 +1,173 @@ > +.. SPDX-License-Identifier: GPL-2.0+ > +.. Copyright (c) 2022 Linaro Limited > + > +FWU Multi Bank Updates in U-Boot > + > + > +The FWU Multi Bank Update feature implements the firmware update > +mechanism described in the PSA Firmware Update for A-profile Arm > +Architecture specification [1]. Certain aspects of the Dependable > +Boot specification [2] are also implemented. The feature provides a > +mechanism to have multiple banks of updatable firmware images and for > +updating the firmware images on the non-booted bank. On a successful > +update, the platform boots from the updated bank on subsequent > +boot. The UEFI capsule-on-disk update feature is used for performing > +the actual updates of the updatable firmware images. > + > +The bookkeeping of the updatable images is done through a structure > +called metadata. Currently, the FWU metadata supports identification > +of images based on image GUIDs stored on a GPT partitioned storage > +media. There are plans to extend the metadata structure for non GPT > +partitioned devices as well. > + > +Accessing the FWU metadata is done through generic API's which are > +defined in a driver which complies with the U-Boot's driver model. A > +new uclass UCLASS_FWU_MDATA has been added for accessing the FWU > +metadata. Individual drivers can be added based on the type of storage > +media, and its partitioning method. Details of the storage device > +containing the FWU metadata partitions are specified through a U-Boot > +specific device tree property `fwu-mdata-store`. Please refer to > +U-Boot `doc `__ > +for the device tree bindings. > + > +Enabling the FWU Multi Bank Update feature > +-- > + > +The feature can be enabled by specifying the following configs:: > + > +CONFIG_EFI_CAPSULE_ON_DISK=y > +CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y > +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y > + > +CONFIG_FWU_MULTI_BANK_UPDATE=y > +CONFIG_CMD_FWU_METADATA=y Actually the command is optional. Even without cmd support, capsules can be consumed from CAPSULE_ON_DISK_EARLY. Is it worth mentioning here? > +CONFIG_FWU_MDATA=y > +CONFIG_FWU_MDATA_GPT_BLK=y > +CONFIG_FWU_NUM_BANKS= > +CONFIG_FWU_NUM_IMAGES_PER_BANK= > + > +in the .config file > + > +The first group of configuration settings enable the UEFI > +capsule-on-disk update functionality. The second group of configs > +enable the FWU Multi Bank Update functionality. Please refer to the > +section :ref:`uefi_capsule_update_ref` for more details on generation > +of the UEFI capsule. > + > +Setting up the device for GPT partitioned storage > +- > + > +Before enabling the functionality in U-Boot, a GPT partitioned storage > +device is required. Assuming a GPT partitioned storage device, the > +storage media needs to be partitioned with the correct number of > +partitions, given the number of banks and number of images per bank > +that the platform is going to support. Each updatable firmware image > +will be stored on a separate partition. In addition, the two copies > +of the FWU metadata will be stored on two separate partitions. > + > +As an example, a platform supporting two banks with each bank > +containing three images would need to have 2 * 3 = 6 partitions plus > +the two metadata partitions, or 8 partitions. In addition the storage > +media can have additional partitions of non-updatable images, like the > +EFI System Partition(ESP), a partition for the root file system > +etc. An example list of images on the storage medium would be > + > +* FWU metadata 1 > +* U-Boot 1 > +* OP-TEE 1 > +* FWU metadata 2 > +* OP-TEE 2 > +* U-Boot 2 > +* ESP > +* rootfs Here or below, maybe mention FWU metadata1/2 and ESP (at least) expect dedicated partition type guid and reference the 2 U-Boot
Re: [PATCH v10 10/15] FWU: Add support for the FWU Multi Bank Update feature
Hello Jassi, On Wed, 28 Sept 2022 at 17:17, Jassi Brar wrote: > > Hi Etienne, > > On Wed, Sep 28, 2022 at 2:30 AM Etienne Carriere > wrote: > > Hello Jassi, Sughosh and all, > > > > >>> But a malicious user may force some old vulnerable image back into use > > >>> by updating all but that image. > > > > When the system boots with accepted images (referring to fwu-mdata > > regular/trial state), the platform monotonic counter is updated > > against booted image version number if needed, preventing older images > > to be booted when an accepted image has been deployed. > > @Jassi, does this answer your question? > > > As I said in my earlier post, I know we can employ security+integrity > techniques to prevent such misuse. > My point is FWU should still be implemented assuming no such technique > might be available due to any reason, and we do the best we can. Just > as we don't say lets not care about buffer-overflow vulnerabilities > because the system can implement secure boot and other such > techniques. > > For example, the spec warns : "The metadata can be maliciously > crafted, it should be treated as an insecure information source." So > clearly the spec doesn't count on rollback and authentication > mechanisms to be always available - and that is how it should be. It is true fwu metadata content are not secure, as the GPT content itself. We cannot prevent OS from corrupting fwu-mdata partitions or the device GPT despite the boot sequence heavily relies on their information. When fwu mdata and GPT are not secure, FWU only allows updating boot image, it cannot secure them. Early boot stage (tf-a) is in charge of verifying booted images (authent. and rollback counter), whatever the booted images are. Best regards, etienne > > cheers.
Re: [PATCH v12 06/15] FWU: Add helper functions for accessing FWU metadata
On Mon, 3 Oct 2022 at 16:25, Sughosh Ganu wrote: > > Add weak functions for getting the update index value and dfu > alternate number needed for FWU Multi Bank update > functionality. > > The current implementation for getting the update index value is for > platforms with 2 banks. If a platform supports more than 2 banks, it > can implement it's own function. The function to get the dfu alternate > number has been added for platforms with GPT partitioned storage > devices. Platforms with other storage partition scheme need to > implement their own function. > > Signed-off-by: Sughosh Ganu > Reviewed-by: Patrick Delaunay > Acked-by: Etienne Carriere > --- > Changes since V11: > * Add a function fwu_alt_num_for_dfu_dev() to get the alt number based > on the DFU backend device as suggested by Ilias > * Change the logic of fwu_gpt_get_alt_num() as suggested by Ilias > > include/fwu.h | 29 ++ > lib/fwu_updates/fwu.c | 27 + > lib/fwu_updates/fwu_gpt.c | 119 ++ > 3 files changed, 175 insertions(+) > create mode 100644 lib/fwu_updates/fwu_gpt.c > > diff --git a/include/fwu.h b/include/fwu.h > index 167f91388e..99f43f07b0 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -212,4 +212,33 @@ int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); > */ > int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); > > +/** > + * fwu_plat_get_alt_num() - Get the DFU Alt Num for the image from the > platform > + * @dev: FWU device > + * @image_guid: Image GUID for which DFU alt number needs to be retrieved > + * @alt_num: Pointer to the alt_num > + * > + * Get the DFU alt number from the platform for the image specified by the > + * image GUID. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid, > +u8 *alt_num); > + > +/** > + * fwu_plat_get_update_index() - Get the value of the update bank > + * @update_idx: Bank number to which images are to be updated > + * > + * Get the value of the bank(partition) to which the update needs to be > + * made. > + * > + * Note: This is a weak function and platforms can override this with > + * their own implementation for selection of the update bank. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +int fwu_plat_get_update_index(uint *update_idx); > #endif /* _FWU_H_ */ > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 439f66aee4..70482d14a0 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -362,3 +362,30 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 > bank) > return fwu_clrset_image_accept(img_type_id, bank, >IMAGE_ACCEPT_CLEAR); > } > + > +/** > + * fwu_plat_get_update_index() - Get the value of the update bank > + * @update_idx: Bank number to which images are to be updated > + * > + * Get the value of the bank(partition) to which the update needs to be > + * made. > + * > + * Note: This is a weak function and platforms can override this with > + * their own implementation for selection of the update bank. > + * > + * Return: 0 if OK, -ve on error > + * > + */ > +__weak int fwu_plat_get_update_index(uint *update_idx) > +{ > + int ret; > + u32 active_idx; > + > + ret = fwu_get_active_index(&active_idx); > + if (ret < 0) > + return -1; > + > + *update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS; > + > + return ret; > +} > diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c > new file mode 100644 > index 00..28bb9756ad > --- /dev/null > +++ b/lib/fwu_updates/fwu_gpt.c > @@ -0,0 +1,119 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t > *image_guid) > +{ > + int i; > + struct disk_partition info; > + efi_guid_t unique_part_guid; > + > + for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { > + if (part_get_info(desc, i, &info)) > + continue; > + uuid_str_to_bin(info.uuid, unique_part_guid.b, > + UUID_STR_FORMAT_GUID); > + > + if (!guidcmp(&unique_part_guid, image_guid)) > + return i; > + } >
Re: [PATCH v13 12/15] test: dm: Add test cases for FWU Metadata uclass
Hi Sughosh, On Thu, 6 Oct 2022 at 11:07, Sughosh Ganu wrote: > > Add test cases for accessing the FWU Metadata on the sandbox > platform. The sandbox platform also uses the metadata access driver > for GPT partitioned block devices. > > The FWU feature will be tested on the sandbox64 variant with a raw > capsule. Remove the FIT capsule testing from sandbox64 defconfig -- > the FIT capsule test will be run on the sandbox_flattree variant. > > Signed-off-by: Sughosh Ganu > Suggested-by: Heinrich Schuchardt > --- > Changes since V12: None > > arch/sandbox/Kconfig | 6 + > arch/sandbox/dts/test.dts | 7 +- > board/sandbox/sandbox.c | 8 + > configs/sandbox64_defconfig | 5 +- > lib/fwu_updates/fwu.c | 6 + > test/dm/Makefile | 1 + > test/dm/fwu_mdata.c | 149 ++ > test/dm/fwu_mdata_disk_image.h| 112 + > .../test_capsule_firmware_fit.py | 1 - > .../test_capsule_firmware_signed_fit.py | 1 - > tools/Makefile| 2 +- > 11 files changed, 293 insertions(+), 5 deletions(-) > create mode 100644 test/dm/fwu_mdata.c > create mode 100644 test/dm/fwu_mdata_disk_image.h > > diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig > index 852a7c8bf2..40cdea7d46 100644 > --- a/arch/sandbox/Kconfig > +++ b/arch/sandbox/Kconfig > @@ -84,3 +84,9 @@ config SYS_FDT_LOAD_ADDR > See `doc/arch/sandbox.rst` for more information. > > endmenu > + > +config FWU_NUM_BANKS > + default 2 > + > +config FWU_NUM_IMAGES_PER_BANK > + default 2 > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts > index 4ee471238e..a4f6fc3abe 100644 > --- a/arch/sandbox/dts/test.dts > +++ b/arch/sandbox/dts/test.dts > @@ -950,7 +950,7 @@ > }; > > /* This is used for the fastboot tests */ > - mmc0 { > + mmc0: mmc0 { > compatible = "sandbox,mmc"; > }; > > @@ -1690,6 +1690,11 @@ > compatible = "sandbox,regmap_test"; > }; > }; > + > + fwu-mdata { > + compatible = "u-boot,fwu-mdata-gpt"; > + fwu-mdata-store = <&mmc0>; > + }; > }; > > #include "sandbox_pmic.dtsi" > diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c > index ca9a2ca5b1..c3d0c35444 100644 > --- a/board/sandbox/sandbox.c > +++ b/board/sandbox/sandbox.c > @@ -164,3 +164,11 @@ int init_addr_map(void) > > return 0; > } > + > +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) > +void fwu_plat_get_bootidx(uint *boot_idx) > +{ > + /* Dummy value */ > + *boot_idx = 0; > +} > +#endif > diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig > index b20b181ab1..8b0d35f484 100644 > --- a/configs/sandbox64_defconfig > +++ b/configs/sandbox64_defconfig > @@ -244,9 +244,12 @@ CONFIG_LZ4=y > CONFIG_ERRNO_STR=y > CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y > CONFIG_EFI_CAPSULE_ON_DISK=y > -CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y > +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y > CONFIG_EFI_SECURE_BOOT=y > CONFIG_TEST_FDTDEC=y > CONFIG_UNIT_TEST=y > CONFIG_UT_TIME=y > CONFIG_UT_DM=y > +CONFIG_FWU_MDATA=y > +CONFIG_FWU_MDATA_GPT_BLK=y > +CONFIG_FWU_MULTI_BANK_UPDATE=y > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index ea8d4144b2..9e3d9e962a 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -551,6 +551,12 @@ static int fwu_boottime_checks(void *ctx, struct event > *event) > struct udevice *dev; > u32 boot_idx, active_idx; > > + /* Don't have boot time checks on sandbox */ > + if (IS_ENABLED(CONFIG_SANDBOX)) { > + boottime_check = 1; > + return 0; > + } > + > ret = fwu_get_dev_mdata(&dev, NULL); > if (ret) > return ret; > diff --git a/test/dm/Makefile b/test/dm/Makefile > index 5178daa7cf..8b2ac9e989 100644 > --- a/test/dm/Makefile > +++ b/test/dm/Makefile > @@ -47,6 +47,7 @@ ifneq ($(CONFIG_EFI_PARTITION),) > obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o > endif > obj-$(CONFIG_FIRMWARE) += firmware.o > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata.o > obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o > obj-$(CONFIG_DM_I2C) += i2c.o > obj-$(CONFIG_SOUND) += i2s.o > diff --git a/test/dm/fwu_mdata.c b/test/dm/fwu_mdata.c > new file mode 100644 > index 00..3401fb64d5 > --- /dev/null > +++ b/test/dm/fwu_mdata.c > @@ -0,0 +1,149 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2022, Linaro Limited > + * Copyright (c) 2022, Heinrich Schuchardt > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include "fwu_mdata_disk_image.h" > + > +/* Block size of compressed disk
Re: [PATCH] tee: optee: rework TA bus scanning code
Hello Ilias, Jens, On Fri, 26 Aug 2022 at 10:46, Jens Wiklander wrote: > > On Tue, Aug 23, 2022 at 10:11 AM Ilias Apalodimas > wrote: > > > > Late versions of OP-TEE support a pseudo bus. TAs that behave as > > hardware blocks (e.g TPM, RNG etc) present themselves on a bus which we can > > scan. Unfortunately U-Boot doesn't support that yet. It's worth noting > > that we already have a workaround for RNG. The details are in > > commit 70812bb83da6 ("tee: optee: bind rng optee driver") > > > > So let's add a list of devices based on U-Boot Kconfig options that we will > > scan until we properly implement the tee-bus functionality. > > > > Signed-off-by: Ilias Apalodimas > > --- > > drivers/tee/optee/core.c | 22 +++--- > > 1 file changed, 19 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > > index a89d62aaf0b3..48a9b59171cb 100644 > > --- a/drivers/tee/optee/core.c > > +++ b/drivers/tee/optee/core.c > > @@ -31,6 +31,20 @@ struct optee_pdata { > > optee_invoke_fn *invoke_fn; > > }; > > > > +static const struct { > > + const char *drv_name; > > + const char *dev_name; > > +} optee_bus_probe[] = { > > +#ifdef CONFIG_RNG_OPTEE > > + { "optee-rng", "optee-rng" }, > > +#endif > > +#ifdef CONFIG_TPM2_FTPM_TEE > > + { "ftpm-tee", "ftpm-tee" }, > > +#endif > > +}; > > + > > +#define MAX_TEE_BUS_DEV_COUNT ARRAY_SIZE(optee_bus_probe) > > + > > struct rpc_param { > > u32 a0; > > u32 a1; > > @@ -643,7 +657,7 @@ static int optee_probe(struct udevice *dev) > > struct optee_pdata *pdata = dev_get_plat(dev); > > u32 sec_caps; > > struct udevice *child; > > - int ret; > > + int ret, i; > > > > if (!is_optee_api(pdata->invoke_fn)) { > > dev_err(dev, "OP-TEE api uid mismatch\n"); > > @@ -672,8 +686,10 @@ static int optee_probe(struct udevice *dev) > > * in U-Boot, the discovery of TA on the TEE bus is not supported: > > * only bind the drivers associated to the supported OP-TEE TA > > */ > > - if (IS_ENABLED(CONFIG_RNG_OPTEE)) { > > - ret = device_bind_driver(dev, "optee-rng", "optee-rng", > > &child); > > + > > + for (i = 0; i < MAX_TEE_BUS_DEV_COUNT; i++) { I would use ARRAY_SIZE(optee_bus_probe) straight here. Macro indirection is not really useful imho. > > + ret = device_bind_driver(dev, optee_bus_probe[i].drv_name, > > +optee_bus_probe[i].dev_name, > > &child); > > if (ret) > > return ret; > > I wonder which behaviour is most useful. Disable OP-TEE support > completely if there's some error when binding dependent drivers or to > just complain a bit but continue. I agree with you, this should better print the status and proceed with the next driver. There are other occurrences of such behaviour in U-Boot. Br, etienne > > Cheers, > Jens > > > > > > } > > -- > > 2.34.1 > >
[PATCH] ARM: dts: stm32mp15: remove hwlocks from pinctrl
Removes hwlocks properties from stm32mp151 pinctrl node. These locks could be used for other purpose, depending on board and software configuration hence do not enforce their use to protect pinctrl devices. This patch is an alignment with Linux device tree with v6.0 as the hwsem support wasn’t yet added in pincontrol in kernel. It avoids issues when the Linux kernel is started with the U-Boot device tree. Cc: Patrice Chotard Cc: Patrick Delaunay Signed-off-by: Etienne Carriere --- arch/arm/dts/stm32mp151.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi index a5ac62c83d..767a06ef68 100644 --- a/arch/arm/dts/stm32mp151.dtsi +++ b/arch/arm/dts/stm32mp151.dtsi @@ -1663,7 +1663,6 @@ ranges = <0 0x50002000 0xa400>; interrupt-parent = <&exti>; st,syscfg = <&exti 0x60 0xff>; - hwlocks = <&hwspinlock 0>; pins-are-numbered; gpioa: gpio@50002000 { @@ -1796,7 +1795,6 @@ pins-are-numbered; interrupt-parent = <&exti>; st,syscfg = <&exti 0x60 0xff>; - hwlocks = <&hwspinlock 0>; gpioz: gpio@54004000 { gpio-controller; -- 2.25.1
Re: [PATCH v2] tee: optee: rework TA bus scanning code
Hi Ilias, Reviewed-by: Etienne Carriere with minor comments. On Fri, 2 Sept 2022 at 21:11, Ilias Apalodimas wrote: > > Thanks Jens > > On Wed, 31 Aug 2022 at 08:59, Jens Wiklander > wrote: > > > > On Mon, Aug 29, 2022 at 8:34 AM Ilias Apalodimas > > wrote: > > > > > > Late versions of OP-TEE support a pseudo bus. TAs that behave as > > > hardware blocks (e.g TPM, RNG etc) present themselves on a bus which we > > > can > > > scan. Unfortunately U-Boot doesn't support that yet. It's worth noting > > > that we already have a workaround for RNG. The details are in > > > commit 70812bb83da6 ("tee: optee: bind rng optee driver") > > > > > > So let's add a list of devices based on U-Boot Kconfig options that we > > > will > > > scan until we properly implement the tee-bus functionality. > > > > > > While at it change the behaviour of the tee core itself wrt to device > > > binding. If some device binding fails, print a warning instead of > > > disabling OP-TEE. > > > > > > Signed-off-by: Ilias Apalodimas > > > --- > > > > Reviewed-by: Jens Wiklander > > There's a typo in that patch. For the tpm to work the string needs to > be ftpm_tee instead of ftpm-tee. I'll send a v3, shall I keep your > RB? > > Cheers > /Ilias > > > > Cheers, > > Jens > > > > > Changes since v1: > > > - remove a macro and use ARRAY_SIZE directly > > > - print a warning instead of disabling op-tee if a driver binding fails > > > > > > drivers/tee/optee/core.c | 23 +++ > > > 1 file changed, 19 insertions(+), 4 deletions(-) > > > > > > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > > > index a89d62aaf0b3..3cc92f09d299 100644 > > > --- a/drivers/tee/optee/core.c > > > +++ b/drivers/tee/optee/core.c > > > @@ -31,6 +31,18 @@ struct optee_pdata { > > > optee_invoke_fn *invoke_fn; > > > }; > > > > > > +static const struct { > > > + const char *drv_name; > > > + const char *dev_name; > > > +} optee_bus_probe[] = { > > > +#ifdef CONFIG_RNG_OPTEE > > > + { "optee-rng", "optee-rng" }, By the way, prefer: + { .drv_name = "optee-rng", .dev_name = "optee-rng" }, > > > +#endif > > > +#ifdef CONFIG_TPM2_FTPM_TEE > > > + { "ftpm-tee", "ftpm-tee" }, > > > +#endif > > > +}; > > > + > > > struct rpc_param { > > > u32 a0; > > > u32 a1; > > > @@ -643,7 +655,7 @@ static int optee_probe(struct udevice *dev) > > > struct optee_pdata *pdata = dev_get_plat(dev); > > > u32 sec_caps; > > > struct udevice *child; > > > - int ret; > > > + int ret, i; > > > > > > if (!is_optee_api(pdata->invoke_fn)) { > > > dev_err(dev, "OP-TEE api uid mismatch\n"); > > > @@ -672,10 +684,13 @@ static int optee_probe(struct udevice *dev) > > > * in U-Boot, the discovery of TA on the TEE bus is not supported: > > > * only bind the drivers associated to the supported OP-TEE TA > > > */ > > > - if (IS_ENABLED(CONFIG_RNG_OPTEE)) { > > > - ret = device_bind_driver(dev, "optee-rng", "optee-rng", > > > &child); > > > + > > > + for (i = 0; i < ARRAY_SIZE(optee_bus_probe); i++) { > > > + ret = device_bind_driver(dev, optee_bus_probe[i].drv_name, > > > +optee_bus_probe[i].dev_name, > > > &child); Can drop child here. NULL is fine. > > > if (ret) > > > - return ret; > > > + dev_warn(dev, "Failed to bind device %s\n", > > > +optee_bus_probe[i].dev_name); > > > } > > > > > > return 0; > > > -- > > > 2.34.1 > > >
Re: [PATCH v3] tee: optee: rework TA bus scanning code
Hi Ilias, I commented v2 instead of you're latest post. Please find my few comments below. Addressed or not, Reviewed-by: Etienne Carriere On Sat, 3 Sept 2022 at 09:54, Ilias Apalodimas wrote: > > Late versions of OP-TEE support a pseudo bus. TAs that behave as > hardware blocks (e.g TPM, RNG etc) present themselves on a bus which we can > scan. Unfortunately U-Boot doesn't support that yet. It's worth noting > that we already have a workaround for RNG. The details are in > commit 70812bb83da6 ("tee: optee: bind rng optee driver") > > So let's add a list of devices based on U-Boot Kconfig options that we will > scan until we properly implement the tee-bus functionality. > > While at it change the behaviour of the tee core itself wrt to device > binding. If some device binding fails, print a warning instead of > disabling OP-TEE. > > Signed-off-by: Ilias Apalodimas > Reviewed-by: Jens Wiklander > --- > Changes since v:2 > - Fixed typo on driver name ftpm-tee -> ftpm_tee > > Changes since v1: > - remove a macro and use ARRAY_SIZE directly > - print a warning instead of disabling op-tee if a driver binding fails > drivers/tee/optee/core.c | 23 +++ > 1 file changed, 19 insertions(+), 4 deletions(-) > > diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c > index a89d62aaf0b3..1437ba1b676b 100644 > --- a/drivers/tee/optee/core.c > +++ b/drivers/tee/optee/core.c > @@ -31,6 +31,18 @@ struct optee_pdata { > optee_invoke_fn *invoke_fn; > }; > > +static const struct { > + const char *drv_name; > + const char *dev_name; > +} optee_bus_probe[] = { > +#ifdef CONFIG_RNG_OPTEE > + { "optee-rng", "optee-rng" }, Prefer { .drv_name = "optee-rng", .dev_name = "optee-rng" }, > +#endif > +#ifdef CONFIG_TPM2_FTPM_TEE > + { "ftpm_tee", "ftpm_tee" }, > +#endif > +}; > + > struct rpc_param { > u32 a0; > u32 a1; > @@ -643,7 +655,7 @@ static int optee_probe(struct udevice *dev) > struct optee_pdata *pdata = dev_get_plat(dev); > u32 sec_caps; > struct udevice *child; > - int ret; > + int ret, i; > > if (!is_optee_api(pdata->invoke_fn)) { > dev_err(dev, "OP-TEE api uid mismatch\n"); > @@ -672,10 +684,13 @@ static int optee_probe(struct udevice *dev) > * in U-Boot, the discovery of TA on the TEE bus is not supported: > * only bind the drivers associated to the supported OP-TEE TA > */ > - if (IS_ENABLED(CONFIG_RNG_OPTEE)) { > - ret = device_bind_driver(dev, "optee-rng", "optee-rng", > &child); > + > + for (i = 0; i < ARRAY_SIZE(optee_bus_probe); i++) { > + ret = device_bind_driver(dev, optee_bus_probe[i].drv_name, > +optee_bus_probe[i].dev_name, &child); Could s/&child/NULL/. Br, etienne > if (ret) > - return ret; > + dev_warn(dev, "Failed to bind device %s\n", > +optee_bus_probe[i].dev_name); > } > > return 0; > -- > 2.34.1 >
Re: [PATCH v5 5/6] fwu: DeveloperBox: add support for FWU
Hello Jassi, On Tue, 11 Apr 2023 at 01:04, wrote: > > From: Jassi Brar > > Add code to support FWU_MULTI_BANK_UPDATE. > The platform does not have gpt-partition storage for > Banks and MetaData, rather it used SPI-NOR backed > mtd regions for the purpose. > I think you should mention this change enables EFI secure boot. > Signed-off-by: Jassi Brar > --- > board/socionext/developerbox/Makefile | 1 + > board/socionext/developerbox/developerbox.c | 8 + > board/socionext/developerbox/fwu_plat.c | 37 + > configs/synquacer_developerbox_defconfig| 8 + > doc/board/socionext/developerbox.rst| 155 +++- > include/configs/synquacer.h | 10 ++ > 6 files changed, 213 insertions(+), 6 deletions(-) > create mode 100644 board/socionext/developerbox/fwu_plat.c > > diff --git a/board/socionext/developerbox/Makefile > b/board/socionext/developerbox/Makefile > index 4a46de995a..1acd067a7e 100644 > --- a/board/socionext/developerbox/Makefile > +++ b/board/socionext/developerbox/Makefile > @@ -7,3 +7,4 @@ > # > > obj-y := developerbox.o > +obj-$(CONFIG_FWU_MDATA_MTD) += fwu_plat.o > diff --git a/board/socionext/developerbox/developerbox.c > b/board/socionext/developerbox/developerbox.c > index 16e14d4f7f..ce2cccf4f0 100644 > --- a/board/socionext/developerbox/developerbox.c > +++ b/board/socionext/developerbox/developerbox.c > @@ -20,6 +20,13 @@ > > #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) > struct efi_fw_image fw_images[] = { > +#if CONFIG_IS_ENABLED(FWU_MULTI_BANK_UPDATE) > + { > + .image_type_id = DEVELOPERBOX_FIP_IMAGE_GUID, > + .fw_name = u"DEVELOPERBOX-FIP", > + .image_index = 1, > + }, > +#else > { > .image_type_id = DEVELOPERBOX_UBOOT_IMAGE_GUID, > .fw_name = u"DEVELOPERBOX-UBOOT", > @@ -35,6 +42,7 @@ struct efi_fw_image fw_images[] = { > .fw_name = u"DEVELOPERBOX-OPTEE", > .image_index = 3, > }, > +#endif > }; > > struct efi_capsule_update_info update_info = { > diff --git a/board/socionext/developerbox/fwu_plat.c > b/board/socionext/developerbox/fwu_plat.c > new file mode 100644 > index 00..e5dae0ff11 > --- /dev/null > +++ b/board/socionext/developerbox/fwu_plat.c > @@ -0,0 +1,37 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2023, Linaro Limited > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#define DFU_ALT_BUF_LEN 256 > + > +/* Generate dfu_alt_info from partitions */ > +void set_dfu_alt_info(char *interface, char *devstr) > +{ > + int ret; > + struct mtd_info *mtd; > + > + ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); ALLOC_CACHE_ALIGN_BUFFER() should be used within local variable definitions at block entry. Prefer: + ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN); + struct mtd_info *mtd; + int ret; + > + memset(buf, 0, sizeof(buf)); > + > + mtd_probe_devices(); > + > + mtd = get_mtd_device_nm("nor1"); > + if (IS_ERR_OR_NULL(mtd)) > + return; > + > + ret = fwu_gen_alt_info_from_mtd(buf, DFU_ALT_BUF_LEN, mtd); > + if (ret < 0) { > + log_err("Error: Failed to generate dfu_alt_info. (%d)\n", > ret); > + return; > + } > + log_debug("Make dfu_alt_info: '%s'\n", buf); > + > + env_set("dfu_alt_info", buf); > +} > diff --git a/configs/synquacer_developerbox_defconfig > b/configs/synquacer_developerbox_defconfig > index 09e12b739b..d09684153a 100644 > --- a/configs/synquacer_developerbox_defconfig > +++ b/configs/synquacer_developerbox_defconfig > @@ -97,3 +97,11 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y > CONFIG_EFI_CAPSULE_ON_DISK=y > CONFIG_EFI_IGNORE_OSINDICATIONS=y > CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y > +CONFIG_EFI_SECURE_BOOT=y > +CONFIG_FWU_MULTI_BANK_UPDATE=y > +CONFIG_FWU_MDATA=y > +CONFIG_FWU_MDATA_MTD=y > +CONFIG_FWU_NUM_BANKS=2 > +CONFIG_FWU_NUM_IMAGES_PER_BANK=1 > +CONFIG_CMD_FWU_METADATA=y > +CONFIG_TOOLS_MKFWUMDATA=y > diff --git a/doc/board/socionext/developerbox.rst > b/doc/board/socionext/developerbox.rst > index 2d943c23be..908d3a7e6f 100644 > --- a/doc/board/socionext/developerbox.rst > +++ b/doc/board/socionext/developerbox.rst > @@ -57,14 +57,20 @@ Installation > > You can install the SNI_NOR_UBOOT.fd via NOR flash writer. > > -Flashing the U-Boot image on DeveloperBox requires a 96boards UART mezzanine > or other mezzanine which can connect to LS-UART0 port. > -Connect USB cable from host to the LS-UART0 and set DSW2-7 to ON, and turn > the board on again. The flash writer program will be started automatically; > don’t forget to turn the DSW2-7 off again after flashing. > +Flashing the U-Boot image on DeveloperBox requires a 96boards UART mezzanine > +or other mezzanine which can connect to LS-UART0 port. nitpicking: ...to **the** LS-UART0.. > +Conn
Re: [PATCH v5 4/6] configs: move to new flash layout and boot flow
Hello Jassi, On Tue, 11 Apr 2023 at 01:04, wrote: > > From: Jassi Brar > > Towards enabling FWU and supporting new firmware layout in NOR flash, > make u-boot PIC and adjust uboot env offset in flash. > > Signed-off-by: Jassi Brar > --- > configs/synquacer_developerbox_defconfig | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) I think the commit header line should mention developerbox defconfig. Aside from that, Acked-by: Etienne Carriere fwiw. Regards, Etienne > > diff --git a/configs/synquacer_developerbox_defconfig > b/configs/synquacer_developerbox_defconfig > index 08f19a90cb..09e12b739b 100644 > --- a/configs/synquacer_developerbox_defconfig > +++ b/configs/synquacer_developerbox_defconfig > @@ -1,12 +1,12 @@ > CONFIG_ARM=y > CONFIG_ARCH_SYNQUACER=y > -CONFIG_TEXT_BASE=0x0820 > +CONFIG_POSITION_INDEPENDENT=y > CONFIG_SYS_MALLOC_LEN=0x100 > CONFIG_SYS_MALLOC_F_LEN=0x400 > CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y > CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xe000 > CONFIG_ENV_SIZE=0x3 > -CONFIG_ENV_OFFSET=0x30 > +CONFIG_ENV_OFFSET=0x58 > CONFIG_ENV_SECT_SIZE=0x1 > CONFIG_DM_GPIO=y > CONFIG_DEFAULT_DEVICE_TREE="synquacer-sc2a11-developerbox" > -- > 2.34.1 >
Re: [PATCH v5 2/6] tools: Add mkfwumdata tool for FWU metadata image
On Tue, 11 Apr 2023 at 01:03, wrote: > > From: Masami Hiramatsu > > Add 'mkfwumdata' tool to generate FWU metadata image for the meta-data > partition to be used in A/B Update imeplementation. > > Signed-off-by: Sughosh Ganu > Signed-off-by: Jassi Brar > Signed-off-by: Masami Hiramatsu > --- > doc/mkfwumdata.1 | 89 > tools/Kconfig | 9 ++ > tools/Makefile | 4 + > tools/mkfwumdata.c | 334 + > 4 files changed, 436 insertions(+) > create mode 100644 doc/mkfwumdata.1 > create mode 100644 tools/mkfwumdata.c > > diff --git a/doc/mkfwumdata.1 b/doc/mkfwumdata.1 > new file mode 100644 > index 00..7dd718b26e > --- /dev/null > +++ b/doc/mkfwumdata.1 > @@ -0,0 +1,89 @@ > +.\" SPDX-License-Identifier: GPL-2.0-or-later > +.\" Copyright (C) 2023 Jassi Brar > +.TH MKFWUMDATA 1 2023-04-10 U-Boot > +.SH NAME > +mkfwumdata \- create FWU metadata image > +. > +.SH SYNOPSIS > +.SY mkfwumdata > +.OP \-a activeidx > +.OP \-p previousidx > +.OP \-g > +.BI \-i\~ imagecount > +.BI \-b\~ bankcount > +.I UUIDs > +.I outputimage > +.YS > +.SY mkfwumdata > +.B \-h > +.YS > +. > +.SH DESCRIPTION > +.B mkfwumdata > +creates metadata info to be used with FWU. > +. > +.SH OPTIONS > +.TP > +.B \-h > +Print usage information and exit. > +. > +.TP > +.B \-a > +Set > +.IR activeidx > +as the currently active Bank. Default is 0. > +. > +.TP > +.B \-p > +Set > +.IR previousidx > +as the previous active Bank. Default is > +.IR activeidx "-1" > +or > +.IR bankcount "-1," > +whichever is non-negative. > +. > +.TP > +.B \-g > +Convert the > +.IR UUIDs > +as GUIDs before use. > +. > +.TP > +.B \-i > +Specify there are > +.IR imagecount > +images in each bank. > +. > +.TP > +.B \-b > +Specify there are a total of > +.IR bankcount > +banks. > +. > +.TP > +.IR UUIDs > +Comma-separated list of UUIDs required to create the metadata :- > +location_uuid,image_type_uuid, > +. > +.TP > +.IR outputimage > +Specify the name of the metadata image file to be created. > +. > +.SH BUGS > +Please report bugs to the > +.UR https://\:source\:.denx\:.de/\:u-boot/\:u-boot/\:issues > +U-Boot bug tracker > +.UE . > +.SH EXAMPLES > +Create a metadata image with 2 banks and 1 image/bank, BankAct=0, BankPrev=1: > +.PP > +.EX > +.in +4 > +$ \c > +.B mkfwumdata \-a 0 \-p 1 \-b 2 \-i 1 \& > +.in +6 > +.B 17e86d77-41f9-4fd7-87ec-a55df9842de5,\& > +.B 10c36d7d-ca52-b843-b7b9-f9d6c501d108,\& > +.B 5a66a702-99fd-4fef-a392-c26e261a2828,a8f868a1-6e5c-4757-878d-ce63375ef2c0 > \& > +.B fwu-mdata.img > diff --git a/tools/Kconfig b/tools/Kconfig > index 539708f277..6e23f44d55 100644 > --- a/tools/Kconfig > +++ b/tools/Kconfig > @@ -157,4 +157,13 @@ config LUT_SEQUENCE > help > Look Up Table Sequence > > +config TOOLS_MKFWUMDATA > + bool "Build mkfwumdata command" > + default y if FWU_MULTI_BANK_UPDATE > + help > + This command allows users to create a raw image of the FWU > + metadata for initial installation of the FWU multi bank > + update on the board. The installation method depends on > + the platform. > + > endmenu > diff --git a/tools/Makefile b/tools/Makefile > index 38699b069d..1e3fce0b1c 100644 > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -250,6 +250,10 @@ HOSTLDLIBS_mkeficapsule += \ > $(shell pkg-config --libs uuid 2> /dev/null || echo "-luuid") > hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule > > +mkfwumdata-objs := mkfwumdata.o lib/crc32.o > +HOSTLDLIBS_mkfwumdata += -luuid > +hostprogs-$(CONFIG_TOOLS_MKFWUMDATA) += mkfwumdata > + > # We build some files with extra pedantic flags to try to minimize things > # that won't build on some weird host compiler -- though there are lots of > # exceptions for files that aren't complaint. > diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c > new file mode 100644 > index 00..43dabf3b72 > --- /dev/null > +++ b/tools/mkfwumdata.c > @@ -0,0 +1,334 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (c) 2023, Linaro Limited > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* This will dynamically allocate the fwu_mdata */ > +#define CONFIG_FWU_NUM_BANKS 0 > +#define CONFIG_FWU_NUM_IMAGES_PER_BANK 0 > + > +/* Since we can not include fwu.h, redefine version here. */ > +#define FWU_MDATA_VERSION 1 > + > +typedef uint8_t u8; > +typedef int16_t s16; > +typedef uint16_t u16; > +typedef uint32_t u32; > +typedef uint64_t u64; > + > +#include > + > +/* TODO: Endianness conversion may be required for some arch. */ > + > +static const char *opts_short = "b:i:a:p:gh"; > + > +static struct option options[] = { > + {"banks", required_argument, NULL, 'b'}, > + {"images", required_argument, NULL, 'i'}, > + {"guid", required_argument, NULL, 'g'}, > + {"active-bank", required_argument,
Re: [PATCH v5 1/6] FWU: Add FWU metadata access driver for MTD storage regions
Hello Jassi, Few comments below. On Tue, 11 Apr 2023 at 01:03, wrote: > > From: Masami Hiramatsu > > In the FWU Multi Bank Update feature, the information about the > updatable images is stored as part of the metadata, on a separate > region. Add a driver for reading from and writing to the metadata > when the updatable images and the metadata are stored on a raw > MTD region. > The code is divided into core under drivers/fwu-mdata/ and some helper > functions clubbed together under lib/fwu_updates/ > > Signed-off-by: Masami Hiramatsu > Signed-off-by: Jassi Brar > --- > drivers/fwu-mdata/Kconfig | 15 ++ > drivers/fwu-mdata/Makefile | 1 + > drivers/fwu-mdata/raw_mtd.c | 272 > include/fwu.h | 32 + > lib/fwu_updates/Makefile| 1 + > lib/fwu_updates/fwu_mtd.c | 185 > 6 files changed, 506 insertions(+) > create mode 100644 drivers/fwu-mdata/raw_mtd.c > create mode 100644 lib/fwu_updates/fwu_mtd.c > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig > index 36c4479a59..42736a5e43 100644 > --- a/drivers/fwu-mdata/Kconfig > +++ b/drivers/fwu-mdata/Kconfig > @@ -6,6 +6,11 @@ config FWU_MDATA > FWU Metadata partitions reside on the same storage device > which contains the other FWU updatable firmware images. > > +choice > + prompt "Storage Layout Scheme" > + depends on FWU_MDATA > + default FWU_MDATA_GPT_BLK > + > config FWU_MDATA_GPT_BLK > bool "FWU Metadata access for GPT partitioned Block devices" > select PARTITION_TYPE_GUID > @@ -14,3 +19,13 @@ config FWU_MDATA_GPT_BLK > help > Enable support for accessing FWU Metadata on GPT partitioned > block devices. > + > +config FWU_MDATA_MTD > + bool "Raw MTD devices" > + depends on MTD > + help > + Enable support for accessing FWU Metadata on non-partitioned > + (or non-GPT partitioned, e.g. partition nodes in devicetree) > + MTD devices. > + > +endchoice > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile > index 3fee64c10c..06c49747ba 100644 > --- a/drivers/fwu-mdata/Makefile > +++ b/drivers/fwu-mdata/Makefile > @@ -6,3 +6,4 @@ > > obj-$(CONFIG_FWU_MDATA) += fwu-mdata-uclass.o > obj-$(CONFIG_FWU_MDATA_GPT_BLK) += gpt_blk.o > +obj-$(CONFIG_FWU_MDATA_MTD) += raw_mtd.o > diff --git a/drivers/fwu-mdata/raw_mtd.c b/drivers/fwu-mdata/raw_mtd.c > new file mode 100644 > index 00..25c1aa33ec > --- /dev/null > +++ b/drivers/fwu-mdata/raw_mtd.c > @@ -0,0 +1,272 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * Copyright (c) 2023, Linaro Limited > + */ > + > +#define LOG_CATEGORY UCLASS_FWU_MDATA > + > +#include > +#include > +#include > + I think you can remove the empty line. > +#include > +#include > + > +/* Internal helper structure to move data around */ > +struct fwu_mdata_mtd_priv { > + struct mtd_info *mtd; > + char pri_label[50]; > + char sec_label[50]; 50 chars is always enough? Maybe allocate buffer when size is known, e.g. with strdup(). > + u32 pri_offset; > + u32 sec_offset; > +}; > + > +enum fwu_mtd_op { > + FWU_MTD_READ, > + FWU_MTD_WRITE, > +}; > + > +extern struct fwu_mtd_image_info fwu_mtd_images[]; > + > +static bool mtd_is_aligned_with_block_size(struct mtd_info *mtd, u64 size) > +{ > + return !do_div(size, mtd->erasesize); > +} > + > +static int mtd_io_data(struct mtd_info *mtd, u32 offs, u32 size, void *data, > + enum fwu_mtd_op op) > +{ > + struct mtd_oob_ops io_op = {}; > + u64 lock_offs, lock_len; > + size_t len; > + void *buf; > + int ret; > + > + if (!mtd_is_aligned_with_block_size(mtd, offs)) { > + log_err("Offset unaligned with a block (0x%x)\n", > mtd->erasesize); > + return -EINVAL; > + } > + > + lock_offs = offs; lock_offs and offs are the same. Could drop lock_offs and use only offs > + /* This will expand erase size to align with the block size */ > + lock_len = round_up(size, mtd->erasesize); > + > + ret = mtd_unlock(mtd, lock_offs, lock_len); > + if (ret && ret != -EOPNOTSUPP) > + return ret; > + > + if (op == FWU_MTD_WRITE) { > + struct erase_info erase_op = {}; > + > + erase_op.mtd = mtd; > + erase_op.addr = lock_offs; > + erase_op.len = lock_len; > + erase_op.scrub = 0; > + > + ret = mtd_erase(mtd, &erase_op); > + if (ret) > + goto lock; > + } > + > + /* Also, expand the write size to align with the write size */ > + len = round_up(size, mtd->writesize); > + > + buf = memalign(ARCH_DMA_MINALIGN, len); > + if (!buf) { > + ret = -ENOMEM; > + goto lock; > + } > + memset(b
RE: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices
Hello Takahiro-san, Sorry again for this late feedback. Testing the series against stm32mp135f-dk board which is using SCMI resources, I see the board fails to boot. > From: AKASHI Takahiro > To: tr...@konsulko.com, s...@chromium.org > Cc: etienne.carri...@st.com, u-boot@lists.denx.de, > AKASHI Takahiro > Subject: [PATCH v2 01/12] scmi: refactor the code to hide a channel from > devices > Date: Wed, 26 Jul 2023 17:37:57 +0900 [thread overview] > Message-ID: <20230726083808.140780-2-takahiro.aka...@linaro.org> (raw) > In-Reply-To: <20230726083808.140780-1-takahiro.aka...@linaro.org> > > The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel > reference") added an explicit parameter, channel, but it seems to make > the code complex. > > Hiding this parameter will allow for adding a generic (protocol-agnostic) > helper function, i.e. for PROTOCOL_VERSION, in a later patch. > > Signed-off-by: AKASHI Takahiro > > --- > v2 > * new patch > --- > drivers/clk/clk_scmi.c| 27 ++--- > drivers/firmware/scmi/scmi_agent-uclass.c | 74 ++- > drivers/power/regulator/scmi_regulator.c | 27 +++-- > drivers/reset/reset-scmi.c| 19 +- > include/scmi_agent.h | 15 +++-- > 5 files changed, 86 insertions(+), 76 deletions(-) > > diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c > index d172fed24c9d..34a49363a51a 100644 > --- a/drivers/clk/clk_scmi.c > +++ b/drivers/clk/clk_scmi.c > @@ -13,17 +13,8 @@ > #include > #include > > -/** > - * struct scmi_clk_priv - Private data for SCMI clocks > - * @channel: Reference to the SCMI channel to use > - */ > -struct scmi_clk_priv { > - struct scmi_channel *channel; > -}; > - > static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) > { > - struct scmi_clk_priv *priv = dev_get_priv(dev); > struct scmi_clk_protocol_attr_out out; > struct scmi_msg msg = { > .protocol_id = SCMI_PROTOCOL_ID_CLOCK, > @@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, > size_t *num_clocks) > }; > int ret; > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(dev, &msg); > if (ret) > return ret; > > @@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, > size_t *num_clocks) > > static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) > { > - struct scmi_clk_priv *priv = dev_get_priv(dev); > struct scmi_clk_attribute_in in = { > .clock_id = clkid, > }; > @@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int > clkid, char **name) > }; > int ret; > > - ret = devm_scmi_process_msg(dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(dev, &msg); > if (ret) > return ret; > > @@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int > clkid, char **name) > > static int scmi_clk_gate(struct clk *clk, int enable) > { > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); > struct scmi_clk_state_in in = { > .clock_id = clk->id, > .attributes = enable, > @@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable) > in, out); > int ret; > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(clk->dev, &msg); > if (ret) > return ret; > > @@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk) > > static ulong scmi_clk_get_rate(struct clk *clk) > { > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); > struct scmi_clk_rate_get_in in = { > .clock_id = clk->id, > }; > @@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk) > in, out); > int ret; > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(clk->dev, &msg); > if (ret < 0) > return ret; > > @@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk) > > static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) > { > - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); > struct scmi_clk_rate_set_in in = { > .clock_id = clk->id, > .flags = SCMI_CLK_RATE_ROUND_CLOSEST, > @@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong > rate) > in, out); > int ret; > > - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); > + ret = devm_scmi_process_msg(clk->dev, &msg); > if (ret < 0) > return ret; > > @@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong > rate) > > static int scmi_clk_probe(
RE: [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol
Hello Takahiro-san, > From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:37 > > SCMI base protocol is mandatory according to the SCMI specification. > > With this patch, SCMI base protocol can be accessed via SCMI transport > layers. All the commands, except SCMI_BASE_NOTIFY_ERRORS, are supported. > This is because U-Boot doesn't support interrupts and the current transport > layers are not able to handle asynchronous messages properly. > > Signed-off-by: AKASHI Takahiro > --- > v2 > * add helper functions, removing direct uses of ops > * add function descriptions for each of functions in ops A reported typo and a question on use of strcpy(). Otherwise the patch look to me. If you strongly feel strcpy() is safe, please get my R-b tag: Reviewed-by: Etienne Carriere > --- > drivers/firmware/scmi/Makefile | 1 + > drivers/firmware/scmi/base.c | 637 + > include/dm/uclass-id.h | 1 + > include/scmi_protocols.h | 345 ++ > 4 files changed, 984 insertions(+) > create mode 100644 drivers/firmware/scmi/base.c > > diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile > index b2ff483c75a1..1a23d4981709 100644 > --- a/drivers/firmware/scmi/Makefile > +++ b/drivers/firmware/scmi/Makefile > @@ -1,4 +1,5 @@ > obj-y += scmi_agent-uclass.o > +obj-y += base.o > obj-y += smt.o > obj-$(CONFIG_SCMI_AGENT_SMCCC) += smccc_agent.o > obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o > diff --git a/drivers/firmware/scmi/base.c b/drivers/firmware/scmi/base.c > new file mode 100644 > index ..2b61fa650d15 > --- /dev/null > +++ b/drivers/firmware/scmi/base.c > @@ -0,0 +1,637 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * SCMI Base protocol as U-Boot device > + * > + * Copyright (C) 2023 Linaro Limited > + * author: AKASHI Takahiro > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/** > + * scmi_generic_protocol_version - get protocol version > + * @dev: SCMI device > + * @id: SCMI protocol ID > + * @version: Pointer to SCMI protocol version > + * > + * Obtain the protocol version number in @version. > + * > + * Return: 0 on success, error code otherwise > + */ > +int scmi_generic_protocol_version(struct udevice *dev, > + enum scmi_std_protocol id, u32 *version) > +{ > + struct scmi_protocol_version_out out; > + struct scmi_msg msg = { > + .protocol_id = id, > + .message_id = SCMI_PROTOCOL_VERSION, > + .out_msg = (u8 *)&out, > + .out_msg_sz = sizeof(out), > + }; > + int ret; > + > + ret = devm_scmi_process_msg(dev, &msg); > + if (ret) > + return ret; > + if (out.status) > + return scmi_to_linux_errno(out.status); > + > + *version = out.version; > + > + return 0; > +} > + > +/** > + * scmi_base_protocol_version_int - get Base protocol version > + * @dev: SCMI device > + * @version: Pointer to SCMI protocol version > + * > + * Obtain the protocol version number in @version for Base protocol. > + * > + * Return: 0 on success, error code otherwise > + */ > +static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version) > +{ > + return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE, > + version); > +} > + > +/** > + * scmi_protocol_attrs_int - get protocol attributes > + * @dev: SCMI device > + * @num_agents: Number of SCMI agents > + * @num_protocols: Number of SCMI protocols > + * > + * Obtain the protocol attributes, the number of agents and the number > + * of protocols, in @num_agents and @num_protocols respectively, that > + * the device provides. > + * > + * Return: 0 on success, error code otherwise > + */ > +static int scmi_protocol_attrs_int(struct udevice *dev, u32 *num_agents, > + u32 *num_protocols) > +{ > + struct scmi_protocol_attrs_out out; > + struct scmi_msg msg = { > + .protocol_id = SCMI_PROTOCOL_ID_BASE, > + .message_id = SCMI_PROTOCOL_ATTRIBUTES, > + .out_msg = (u8 *)&out, > + .out_msg_sz = sizeof(out), > + }; > + int ret; > + > + ret = devm_scmi_process_msg(dev, &msg); > + if (ret) > + return ret; > + if (out.st
RE: [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:37 > > Move the location of scmi_bind_protocols() backward for changes > in later patches. > There is no change in functionality. > > Signed-off-by: AKASHI Takahiro > --- > drivers/firmware/scmi/scmi_agent-uclass.c | 118 +++--- > 1 file changed, 59 insertions(+), 59 deletions(-) > Reviewed-by: Etienne Carriere > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index 39cf15c88f75..8693e4c447b7 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -52,65 +52,6 @@ int scmi_to_linux_errno(s32 scmi_code) > return -EPROTO; > } > > -/* > - * SCMI agent devices binds devices of various uclasses depeding on > - * the FDT description. scmi_bind_protocol() is a generic bind sequence > - * called by the uclass at bind stage, that is uclass post_bind. > - */ > -static int scmi_bind_protocols(struct udevice *dev) > -{ > - int ret = 0; > - ofnode node; > - const char *name; > - > - dev_for_each_subnode(node, dev) { > - struct driver *drv = NULL; > - u32 protocol_id; > - > - if (!ofnode_is_enabled(node)) > - continue; > - > - if (ofnode_read_u32(node, "reg", &protocol_id)) > - continue; > - > - name = ofnode_get_name(node); > - switch (protocol_id) { > - case SCMI_PROTOCOL_ID_CLOCK: > - if (CONFIG_IS_ENABLED(CLK_SCMI)) > - drv = DM_DRIVER_GET(scmi_clock); > - break; > - case SCMI_PROTOCOL_ID_RESET_DOMAIN: > - if (IS_ENABLED(CONFIG_RESET_SCMI)) > - drv = DM_DRIVER_GET(scmi_reset_domain); > - break; > - case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > - if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) { > - node = ofnode_find_subnode(node, > "regulators"); > - if (!ofnode_valid(node)) { > - dev_err(dev, "no regulators node\n"); > - return -ENXIO; > - } > - drv = DM_DRIVER_GET(scmi_voltage_domain); > - } > - break; > - default: > - break; > - } > - > - if (!drv) { > - dev_dbg(dev, "Ignore unsupported SCMI protocol %#x\n", > - protocol_id); > - continue; > - } > - > - ret = device_bind(dev, drv, name, NULL, node, NULL); > - if (ret) > - break; > - } > - > - return ret; > -} > - > static struct udevice *find_scmi_transport_device(struct udevice *dev) > { > struct udevice *parent = dev; > @@ -208,6 +149,65 @@ int devm_scmi_process_msg(struct udevice *dev, struct > scmi_msg *msg) > return scmi_process_msg(parent, priv->channel, msg); > } > > +/* > + * SCMI agent devices binds devices of various uclasses depeding on > + * the FDT description. scmi_bind_protocol() is a generic bind sequence > + * called by the uclass at bind stage, that is uclass post_bind. > + */ > +static int scmi_bind_protocols(struct udevice *dev) > +{ > + int ret = 0; > + ofnode node; > + const char *name; > + > + dev_for_each_subnode(node, dev) { > + struct driver *drv = NULL; > + u32 protocol_id; > + > + if (!ofnode_is_enabled(node)) > + continue; > + > + if (ofnode_read_u32(node, "reg", &protocol_id)) > + continue; > + > + name = ofnode_get_name(node); > + switch (protocol_id) { > + case SCMI_PROTOCOL_ID_CLOCK: > + if (CONFIG_IS_ENABLED(CLK_SCMI)) > + drv = DM_DRIVER_GET(scmi_clock); > + break; > + case SCMI_PROTOCOL_ID_RESET_DOMAIN: > + if (IS_ENABLED(CONFIG_RESET_SCMI)) > + drv = DM_DRIVER_GET(scmi_reset_domain); > + break; > + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: &g
RE: [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > This framework allows SCMI protocols to be installed and bound to the agent > so that the agent can manage and utilize them later. > > Signed-off-by: AKASHI Takahiro > --- > v2 > * check for availability of protocols Reviewed-by: Etienne Carriere with 2 minor comments and with .per_device_plat_auto value set by this patch instead of from patch v2 01/12. > --- > drivers/firmware/scmi/scmi_agent-uclass.c | 100 +- > include/scmi_agent-uclass.h | 15 +++- > include/scmi_agent.h | 14 +++ > 3 files changed, 125 insertions(+), 4 deletions(-) > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index 8693e4c447b7..2244fcf487e8 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -38,6 +38,86 @@ static const struct error_code scmi_linux_errmap[] = { > { .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, }, > }; > > +/* > + * NOTE: The only one instance should exist according to > + * the current specification and device tree bindings. > + */ > +struct udevice *scmi_agent; > + > +struct udevice *scmi_get_protocol(struct udevice *dev, > + enum scmi_std_protocol id) > +{ > + struct scmi_agent_priv *priv; > + struct udevice *proto; > + > + priv = dev_get_uclass_plat(dev); > + if (!priv) { > + dev_err(dev, "No priv data found\n"); > + return NULL; > + } > + > + switch (id) { > + case SCMI_PROTOCOL_ID_CLOCK: > + proto = priv->clock_dev; > + break; > + case SCMI_PROTOCOL_ID_RESET_DOMAIN: > + proto = priv->resetdom_dev; > + break; > + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > + proto = priv->voltagedom_dev; > + break; > + default: > + dev_err(dev, "Protocol not supported\n"); > + proto = NULL; > + break; > + } > + if (proto && device_probe(proto)) > + dev_err(dev, "Probe failed\n"); > + > + return proto; > +} > + > +/** > + * scmi_add_protocol - add protocol to agent > + * @dev: SCMI agent device > + * @proto_id: SCMI protocol ID > + * @proto: SCMI protocol device > + * > + * Associate the protocol instance, @proto, to the agent, @dev, > + * for later use. > + * > + * Return: 0 on success, error code otherwise > + */ > +static int scmi_add_protocol(struct udevice *dev, > + enum scmi_std_protocol proto_id, > + struct udevice *proto) > +{ > + struct scmi_agent_priv *priv; > + > + priv = dev_get_uclass_plat(dev); > + if (!priv) { > + dev_err(dev, "No priv data found\n"); > + return -ENODEV; > + } > + > + switch (proto_id) { > + case SCMI_PROTOCOL_ID_CLOCK: > + priv->clock_dev = proto; > + break; > + case SCMI_PROTOCOL_ID_RESET_DOMAIN: > + priv->resetdom_dev = proto; > + break; > + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > + priv->voltagedom_dev = proto; > + break; > + default: > + dev_err(dev, "Protocol not supported\n"); > + return -EPROTO; > + } > + > + return 0; > +} > + > int scmi_to_linux_errno(s32 scmi_code) > { > int n; > @@ -156,12 +236,14 @@ int devm_scmi_process_msg(struct udevice *dev, struct > scmi_msg *msg) > */ > static int scmi_bind_protocols(struct udevice *dev) > { > + struct udevice *agent; > int ret = 0; > ofnode node; > const char *name; > + struct driver *drv; > + struct udevice *proto; > > dev_for_each_subnode(node, dev) { > - struct driver *drv = NULL; > u32 protocol_id; > > if (!ofnode_is_enabled(node)) > @@ -170,6 +252,7 @@ static int scmi_bind_protocols(struct udevice *dev) > if (ofnode_read_u32(node, "reg", &protocol_id)) > continue; > > + drv = NULL; > name = ofnode_get_name(node); > switch (protocol_id) { > case SCMI_PROTOCOL_ID_CLOCK: > @@ -200,11 +283,22 @@ static int scmi_bind_protoc
RE: [PATCH v2 05/12] firmware: scmi: install base protocol to SCMI agent
> From: AKASHI Takahiro > Sent: Thursday, July 27, 2023 03:07 > > Hi Simon, > > Thank you for your extensive review. > > On Wed, Jul 26, 2023 at 06:50:23PM -0600, Simon Glass wrote: > > Hi, > > > > On Wed, 26 Jul 2023 at 02:39, AKASHI Takahiro > > wrote: > > > > > > SCMI base protocol is mandatory, and once SCMI node is found in a device > > > tree, the protocol handle (udevice) is unconditionally installed to > > > the agent. Then basic information will be retrieved from SCMI server via > > > the protocol and saved into the agent instance's local storage. > > > > > > Signed-off-by: AKASHI Takahiro > > > --- > > > v2 > > > * use helper functions, removing direct uses of ops > > > --- > > > drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++ > > > include/scmi_agent-uclass.h | 70 - > > > 2 files changed, 184 insertions(+), 2 deletions(-) > > > > > > > Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere with below reported typo preferrably addressed. > > > > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > > > b/drivers/firmware/scmi/scmi_agent-uclass.c > > > index 2244fcf487e8..279c2c218913 100644 > > > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > > > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > > > @@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev, > > > } > > > > > > switch (id) { > > > + case SCMI_PROTOCOL_ID_BASE: > > > + proto = priv->base_dev; > > > + break; > > > case SCMI_PROTOCOL_ID_CLOCK: > > > proto = priv->clock_dev; > > > break; > > > @@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev, > > > } > > > > > > switch (proto_id) { > > > + case SCMI_PROTOCOL_ID_BASE: > > > + priv->base_dev = proto; > > > + break; > > > case SCMI_PROTOCOL_ID_CLOCK: > > > priv->clock_dev = proto; > > > break; > > > @@ -229,6 +235,83 @@ int devm_scmi_process_msg(struct udevice *dev, > > > struct scmi_msg *msg) > > > return scmi_process_msg(parent, priv->channel, msg); > > > } > > > > > > +/** > > > + * scmi_fill_base_info - get base information about SCMI server > > > + * @agent: SCMI agent device > > > + * @dev: SCMI protocol device > > > + * > > > + * By using Base protocol commands, collect the base information > > > + * about SCMI server. > > > + * > > > + * Return: 0 on success, error code otherwise > > > + */ > > > +static int scmi_fill_base_info(struct udevice *agent, struct udevice > > > *dev) > > > +{ > > > + struct scmi_agent_priv *priv = dev_get_uclass_plat(agent); > > > + int ret; > > > + > > > + ret = scmi_base_protocol_version(dev, &priv->version); > > > + if (ret) { > > > + dev_err(dev, "protocol_version() failed (%d)\n", ret); > > > + return ret; > > > + } > > > + /* check for required version */ > > > + if (priv->version < SCMI_BASE_PROTOCOL_VERSION) { > > > + dev_err(dev, "base protocol version (%d) lower than > > > expected\n", > > > + priv->version); > > > + return -EPROTO; > > > + } > > > + > > > + ret = scmi_base_protocol_attrs(dev, &priv->num_agents, > > > + &priv->num_protocols); > > > + if (ret) { > > > + dev_err(dev, "protocol_attrs() failed (%d)\n", ret); > > > + return ret; > > > + } > > > + ret = scmi_base_discover_vendor(dev, priv->vendor); > > > + if (ret) { > > > + dev_err(dev, "base_discover_vendor() failed (%d)\n", ret); > > > + return ret; > > > + } > > > + ret = scmi_base_discover_sub_vendor(dev, priv->sub_vendor); > > > + if (ret) { > > > + if (ret != -EOPNOTSUPP) { > > > + dev_err(dev, "base_d
RE: [PATCH v2 06/12] sandbox: remove SCMI base node definition from test.dts
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > SCMI base protocol is mandatory and doesn't need to be listed in a device > tree. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere > --- > arch/sandbox/dts/test.dts | 4 > 1 file changed, 4 deletions(-) > > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts > index ff9f9222e6f9..2aad94681148 100644 > --- a/arch/sandbox/dts/test.dts > +++ b/arch/sandbox/dts/test.dts > @@ -682,10 +682,6 @@ > #address-cells = <1>; > #size-cells = <0>; > > - protocol@10 { > - reg = <0x10>; > - }; > - > clk_scmi: protocol@14 { > reg = <0x14>; > #clock-cells = <1>; > -- > 2.41.0
RE: [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > This is a simple implementation of SCMI base protocol for sandbox. > The main use is in SCMI unit test. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere with reported typo addressed. > --- > drivers/firmware/scmi/sandbox-scmi_agent.c | 359 - > 1 file changed, 358 insertions(+), 1 deletion(-) > > diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c > b/drivers/firmware/scmi/sandbox-scmi_agent.c > index 031882998dfa..1f0261ea5c94 100644 > --- a/drivers/firmware/scmi/sandbox-scmi_agent.c > +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c > @@ -14,11 +14,14 @@ > #include > #include > #include > +#include > +#include > > /* > * The sandbox SCMI agent driver simulates to some extend a SCMI message > * processing. It simulates few of the SCMI services for some of the > * SCMI protocols embedded in U-Boot. Currently: > + * - SCMI base protocol > * - SCMI clock protocol emulates an agent exposing 2 clocks > * - SCMI reset protocol emulates an agent exposing a reset controller > * - SCMI voltage domain protocol emulates an agent exposing 2 regulators > @@ -33,6 +36,21 @@ > * various uclass devices, as clocks and reset controllers. > */ > > +#define SANDBOX_SCMI_BASE_PROTOCOL_VERSION SCMI_BASE_PROTOCOL_VERSION > +#define SANDBOX_SCMI_VENDOR "U-Boot" > +#define SANDBOX_SCMI_SUB_VENDOR "Sandbox" > +#define SANDBOX_SCMI_IMPL_VERSION 0x1 > +#define SANDBOX_SCMI_AGENT_NAME "OSPM" > +#define SANDBOX_SCMI_PLATFORM_NAME "platform" > + > +static u8 protocols[] = { > + SCMI_PROTOCOL_ID_CLOCK, > + SCMI_PROTOCOL_ID_RESET_DOMAIN, > + SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, > +}; > + > +#define NUM_PROTOCOLS ARRAY_SIZE(protocols) > + > static struct sandbox_scmi_clk scmi_clk[] = { > { .rate = 333 }, > { .rate = 200 }, > @@ -114,6 +132,316 @@ static struct sandbox_scmi_voltd > *get_scmi_voltd_state(uint domain_id) > * Sandbox SCMI agent ops > */ > > +/* Base Protocol */ > + > +/** > + * sandbox_scmi_base_protocol_version - implement SCMI_BASE_PROTOCOL_VERSION > + * @udevice: SCMI device typo: s/udevice/dev/g here and in the other function inline descripion comments below. BR, etienne > + * @msg: SCMI message > + * > + * Implement SCMI_BASE_PROTOCOL_VERSION command. > + */ > +static int sandbox_scmi_base_protocol_version(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct scmi_protocol_version_out *out = NULL; > + > + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) > + return -EINVAL; > + > + out = (struct scmi_protocol_version_out *)msg->out_msg; > + out->version = SANDBOX_SCMI_BASE_PROTOCOL_VERSION; > + out->status = SCMI_SUCCESS; > + > + return 0; > +} > + > +/** > + * sandbox_scmi_base_protocol_attrs - implement SCMI_BASE_PROTOCOL_ATTRIBUTES > + * @udevice: SCMI device > + * @msg: SCMI message > + * > + * Implement SCMI_BASE_PROTOCOL_ATTRIBUTES command. > + */ > +static int sandbox_scmi_base_protocol_attrs(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct scmi_protocol_attrs_out *out = NULL; > + > + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) > + return -EINVAL; > + > + out = (struct scmi_protocol_attrs_out *)msg->out_msg; > + out->attributes = FIELD_PREP(0xff00, 2) | NUM_PROTOCOLS; > + out->status = SCMI_SUCCESS; > + > + return 0; > +} > + > +/** > + * sandbox_scmi_base_message_attrs - implement > + * SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES > + * @udevice: SCMI device > + * @msg: SCMI message > + * > + * Implement SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES command. > + */ > +static int sandbox_scmi_base_message_attrs(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + u32 message_id; > + struct scmi_protocol_msg_attrs_out *out = NULL; > + > + if (!msg->in_msg || msg->in_msg_sz < sizeof(message_id) || > + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) > + return -EINVAL; > + > + message_id = *(u32 *)msg->in_msg; > + out = (struct scmi_protocol_msg_attrs_out *)msg->out_msg; > + > + if (message_id >= SCMI_PROTOCOL_VERSION && > + message_id
RE: [PATCH v2 08/12] test: dm: simplify SCMI unit test on sandbox
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > Adding SCMI base protocol makes it inconvenient to hold the agent instance > (udevice) locally since the agent device will be re-created per each test. > Just remove it and simplify the test flows. > The test scenario is not changed at all. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > --- Reviewed-by: Etienne Carriere > arch/sandbox/include/asm/scmi_test.h | 7 ++- > drivers/firmware/scmi/sandbox-scmi_agent.c | 20 +-- > drivers/firmware/scmi/scmi_agent-uclass.c | 3 - > test/dm/scmi.c | 64 +++--- > 4 files changed, 26 insertions(+), 68 deletions(-) > > diff --git a/arch/sandbox/include/asm/scmi_test.h > b/arch/sandbox/include/asm/scmi_test.h > index c72ec1e1cb25..2718336a9a50 100644 > --- a/arch/sandbox/include/asm/scmi_test.h > +++ b/arch/sandbox/include/asm/scmi_test.h > @@ -89,10 +89,11 @@ struct sandbox_scmi_devices { > > #ifdef CONFIG_SCMI_FIRMWARE > /** > - * sandbox_scmi_service_ctx - Get the simulated SCMI services context > + * sandbox_scmi_agent_ctx - Get the simulated SCMI agent context > + * @dev: Reference to the test agent > * @return: Reference to backend simulated resources state > */ > -struct sandbox_scmi_service *sandbox_scmi_service_ctx(void); > +struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev); > > /** > * sandbox_scmi_devices_ctx - Get references to devices accessed through SCMI > @@ -101,7 +102,7 @@ struct sandbox_scmi_service > *sandbox_scmi_service_ctx(void); > */ > struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev); > #else > -static inline struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) > +static struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev) > { > return NULL; > } > diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c > b/drivers/firmware/scmi/sandbox-scmi_agent.c > index 1f0261ea5c94..ab8afb01de40 100644 > --- a/drivers/firmware/scmi/sandbox-scmi_agent.c > +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c > @@ -66,11 +66,9 @@ static struct sandbox_scmi_voltd scmi_voltd[] = { > { .id = 1, .voltage_uv = 180 }, > }; > > -static struct sandbox_scmi_service sandbox_scmi_service_state; > - > -struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) > +struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev) > { > - return &sandbox_scmi_service_state; > + return dev_get_priv(dev); > } > > static void debug_print_agent_state(struct udevice *dev, char *str) > @@ -898,16 +896,8 @@ static int sandbox_scmi_test_process_msg(struct udevice > *dev, > > static int sandbox_scmi_test_remove(struct udevice *dev) > { > - struct sandbox_scmi_agent *agent = dev_get_priv(dev); > - > - if (agent != sandbox_scmi_service_ctx()->agent) > - return -EINVAL; > - > debug_print_agent_state(dev, "removed"); > > - /* We only need to dereference the agent in the context */ > - sandbox_scmi_service_ctx()->agent = NULL; > - > return 0; > } > > @@ -915,9 +905,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev) > { > struct sandbox_scmi_agent *agent = dev_get_priv(dev); > > - if (sandbox_scmi_service_ctx()->agent) > - return -EINVAL; > - > *agent = (struct sandbox_scmi_agent){ > .clk = scmi_clk, > .clk_count = ARRAY_SIZE(scmi_clk), > @@ -929,9 +916,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev) > > debug_print_agent_state(dev, "probed"); > > - /* Save reference for tests purpose */ > - sandbox_scmi_service_ctx()->agent = agent; > - > return 0; > }; > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index 279c2c218913..91cb172f3005 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -412,9 +412,6 @@ static int scmi_bind_protocols(struct udevice *dev) > } > } > > - if (!ret) > - scmi_agent = dev; > - > return ret; > } > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > index d87e2731ce42..881be3171b7c 100644 > --- a/test/dm/scmi.c > +++ b/test/dm/scmi.c > @@ -23,22 +23,11 @@ > #include > #include > > -static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) > -{ > - st
RE: [PATCH v2 09/12] test: dm: add SCMI base protocol test
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > Added is a new unit test for SCMI base protocol, which will exercise all > the commands provided by the protocol, except SCMI_BASE_NOTIFY_ERRORS. > $ ut dm scmi_base > It is assumed that test.dtb is used as sandbox's device tree. > > Signed-off-by: AKASHI Takahiro > --- > v2 > * use helper functions, removing direct uses of ops > --- Reviewed-by: Etienne Carriere with reported issue fixed. > test/dm/scmi.c | 109 + > 1 file changed, 109 insertions(+) > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > index 881be3171b7c..41d46548f7fd 100644 > --- a/test/dm/scmi.c > +++ b/test/dm/scmi.c > @@ -16,6 +16,9 @@ > #include > #include > #include > +#include > +#include > +#include > #include > #include > #include > @@ -95,6 +98,112 @@ static int dm_test_scmi_sandbox_agent(struct > unit_test_state *uts) > } > DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT); > > +static int dm_test_scmi_base(struct unit_test_state *uts) > +{ > + struct udevice *agent_dev, *base; > + struct scmi_agent_priv *priv; > + u32 version, num_agents, num_protocols, impl_version; > + u32 attributes, agent_id; > + char vendor[SCMI_BASE_NAME_LENGTH_MAX], > + agent_name[SCMI_BASE_NAME_LENGTH_MAX]; > + u8 *protocols; > + int ret; > + > + /* preparation */ > + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", > + &agent_dev)); > + ut_assertnonnull(agent_dev); > + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev)); > + ut_assertnonnull(base = scmi_get_protocol(agent_dev, > + SCMI_PROTOCOL_ID_BASE)); > + > + /* version */ > + ret = scmi_base_protocol_version(base, &version); > + ut_assertok(ret); > + ut_asserteq(priv->version, version); > + > + /* protocol attributes */ > + ret = scmi_base_protocol_attrs(base, &num_agents, &num_protocols); Typo: s/scmi_base_protocol_attrs/scmi_base_protocol_message_attrs/ This issue is fixed in patch 12/12 but should be squashed here to prevent a build error. BR, etienne > + ut_assertok(ret); > + ut_asserteq(priv->num_agents, num_agents); > + ut_asserteq(priv->num_protocols, num_protocols); > + > + /* discover vendor */ > + ret = scmi_base_discover_vendor(base, vendor); > + ut_assertok(ret); > + ut_asserteq_str(priv->vendor, vendor); > + > + /* message attributes */ > + ret = scmi_protocol_message_attrs(base, > + SCMI_BASE_DISCOVER_SUB_VENDOR, > + &attributes); > + ut_assertok(ret); > + ut_assertok(attributes); > + > + /* discover sub vendor */ > + ret = scmi_base_discover_sub_vendor(base, vendor); > + ut_assertok(ret); > + ut_asserteq_str(priv->sub_vendor, vendor); > + > + /* impl version */ > + ret = scmi_base_discover_impl_version(base, &impl_version); > + ut_assertok(ret); > + ut_asserteq(priv->impl_version, impl_version); > + > + /* discover agent (my self) */ > + ret = scmi_base_discover_agent(base, 0x, &agent_id, > agent_name); > + ut_assertok(ret); > + ut_asserteq(priv->agent_id, agent_id); > + ut_asserteq_str(priv->agent_name, agent_name); > + > + /* discover protocols */ > + ret = scmi_base_discover_list_protocols(base, &protocols); > + ut_asserteq(num_protocols, ret); > + ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * > num_protocols); > + free(protocols); > + > + /* > + * NOTE: Sandbox SCMI driver handles device-0 only. It supports > setting > + * access and protocol permissions, but doesn't allow unsetting them > nor > + * resetting the configurations. > + */ > + /* set device permissions */ > + ret = scmi_base_set_device_permissions(base, agent_id, 0, > + > SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS); > + ut_assertok(ret); /* SCMI_SUCCESS */ > + ret = scmi_base_set_device_permissions(base, agent_id, 1, > + > SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS); > + ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */ > + ret = scmi_base_set_device_permi
RE: [PATCH v2 10/12] cmd: add scmi command for SCMI firmware
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > This command, "scmi", may provide a command line interface to various SCMI > protocols. It supports at least initially SCMI base protocol and is > intended mainly for debug purpose. > > Signed-off-by: AKASHI Takahiro > --- > v2 > * remove sub command category, 'scmi base', for simplicity Reviewed-by: Etienne Carriere > --- > cmd/Kconfig | 9 ++ > cmd/Makefile | 1 + > cmd/scmi.c | 334 +++ > 3 files changed, 344 insertions(+) > create mode 100644 cmd/scmi.c > > diff --git a/cmd/Kconfig b/cmd/Kconfig > index 02e54f1e50fe..15d1d7b9863f 100644 > --- a/cmd/Kconfig > +++ b/cmd/Kconfig > @@ -2504,6 +2504,15 @@ config CMD_CROS_EC > a number of sub-commands for performing EC tasks such as > updating its flash, accessing a small saved context area > and talking to the I2C bus behind the EC (if there is one). > + > +config CMD_SCMI > + bool "Enable scmi command" > + depends on SCMI_FIRMWARE > + default n > + help > + This command provides user interfaces to several SCMI (System > + Control and Management Interface) protocols available on Arm > + platforms to manage system resources. > endmenu > > menu "Filesystem commands" > diff --git a/cmd/Makefile b/cmd/Makefile > index 6c37521b4e2b..826e0b74b587 100644 > --- a/cmd/Makefile > +++ b/cmd/Makefile > @@ -156,6 +156,7 @@ obj-$(CONFIG_CMD_SATA) += sata.o > obj-$(CONFIG_CMD_NVME) += nvme.o > obj-$(CONFIG_SANDBOX) += sb.o > obj-$(CONFIG_CMD_SF) += sf.o > +obj-$(CONFIG_CMD_SCMI) += scmi.o > obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o > obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o > obj-$(CONFIG_CMD_SEAMA) += seama.o > diff --git a/cmd/scmi.c b/cmd/scmi.c > new file mode 100644 > index ..5ecd9051b48d > --- /dev/null > +++ b/cmd/scmi.c > @@ -0,0 +1,334 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * SCMI (System Control and Management Interface) utility command > + * > + * Copyright (c) 2023 Linaro Limited > + * Author: AKASHI Takahiro > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include /* uclass_get_device */ > +#include > +#include > + > +static struct udevice *agent; > +static struct udevice *base_proto; > + > +struct { > + enum scmi_std_protocol id; > + const char *name; > +} protocol_name[] = { > + {SCMI_PROTOCOL_ID_BASE, "Base"}, > + {SCMI_PROTOCOL_ID_POWER_DOMAIN, "Power domain management"}, > + {SCMI_PROTOCOL_ID_SYSTEM, "System power management"}, > + {SCMI_PROTOCOL_ID_PERF, "Performance domain management"}, > + {SCMI_PROTOCOL_ID_CLOCK, "Clock management"}, > + {SCMI_PROTOCOL_ID_SENSOR, "Sensor management"}, > + {SCMI_PROTOCOL_ID_RESET_DOMAIN, "Reset domain management"}, > + {SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, "Voltage domain management"}, > +}; > + > +/** > + * get_proto_name() - get the name of SCMI protocol > + * > + * @id: SCMI Protocol ID > + * > + * Get the printable name of the protocol, @id > + * > + * Return: Name string on success, NULL on failure > + */ > +static const char *get_proto_name(enum scmi_std_protocol id) > +{ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(protocol_name); i++) > + if (id == protocol_name[i].id) > + return protocol_name[i].name; > + > + return NULL; > +} > + > +/** > + * do_scmi_info() - get the information of SCMI services > + * > + * @cmdtp: Command table > + * @flag: Command flag > + * @argc: Number of arguments > + * @argv: Argument array > + * > + * Get the information of SCMI services using various interfaces > + * provided by the Base protocol. > + * > + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure > + */ > +static int do_scmi_info(struct cmd_tbl *cmdtp, int flag, int argc, > + char * const argv[]) > +{ > + u32 agent_id, num_protocols; > + u8 agent_name[SCMI_BASE_NAME_LENGTH_MAX], *protocols; > + int i, ret; > + > + if (argc != 1) > + return CMD_RET_USAGE; > + > + printf("SCMI device: %s\n", agent->name); > + printf(" protocol version: 0x%x\n", scmi_version(agent)); > + printf(" # of agents: %d\n&
RE: [PATCH v2 11/12] doc: cmd: add documentation for scmi
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > This is a help text for scmi command. > > Signed-off-by: AKASHI Takahiro > --- > v2 > * add more descriptions about SCMI Reviewed-by: Etienne Carriere > --- > doc/usage/cmd/scmi.rst | 126 + > 1 file changed, 126 insertions(+) > create mode 100644 doc/usage/cmd/scmi.rst > > diff --git a/doc/usage/cmd/scmi.rst b/doc/usage/cmd/scmi.rst > new file mode 100644 > index ..aebcfe95101d > --- /dev/null > +++ b/doc/usage/cmd/scmi.rst > @@ -0,0 +1,126 @@ > +.. SPDX-License-Identifier: GPL-2.0+: > + > +scmi command > + > + > +Synopsis > + > + > +:: > + > + scmi info > + scmi perm_dev > + scmi perm_proto > + scmi reset > + > +Description > +--- > + > +Arm System Control and Management Interface (SCMI hereafter) is a set of > +standardised interfaces to manage system resources, like clocks, power > +domains, pin controls, reset and so on, in a system-wide manner. > + > +An entity which provides those services is called a SCMI firmware (or > +SCMI server if you like) may be placed/implemented by EL3 software or > +by a dedicated system control processor (SCP) or else. > + > +A user of SCMI interfaces, including U-Boot, is called a SCMI agent and > +may issues commands, which are defined in each protocol for specific system > +resources, to SCMI server via a communication channel, called a transport. > +Those interfaces are independent from the server's implementation thanks to > +a tranport layer. > + > +For more details, see the `SCMI specification`_. > + > +While most of system resources managed under SCMI protocols are implemented > +and handled as standard U-Boot devices, for example clk_scmi, scmi command > +provides additional management functionality against SCMI server. > + > +scmi info > +~ > + Show base information about SCMI server and supported protocols > + > +scmi perm_dev > +~ > + Allow or deny access permission to the device > + > +scmi perm_proto > +~~~ > + Allow or deny access to the protocol on the device > + > +scmi reset > +~~ > + Reset the already-configured permissions against the device > + > +Parameters are used as follows: > + > + > + SCMI Agent ID, hex value By the way, this documentation states hexadecimal value are awaited but not the embedded doc (patch v2 10/12). Would it be worth it? > + > + > + SCMI Device ID, hex value > + > + Please note that what a device means is not defined > + in the specification. > + > + > + SCMI Protocol ID, hex value > + > + It must not be 0x10 (base protocol) > + > + > + Flags to control the action, hex value > + > + 0 to deny, 1 to allow. The other values are reserved and allowed > + values may depend on the implemented version of SCMI server in > + the future. See SCMI specification for more details. > + > +Example > +--- > + > +Obtain basic information about SCMI server: > + > +:: > + > + => scmi info > + SCMI device: scmi > + protocol version: 0x2 > + # of agents: 3 > + 0: platform > + > 1: OSPM > + 2: PSCI > + # of protocols: 4 > + Power domain management > + Performance domain management > + Clock management > + Sensor management > + vendor: Linaro > + sub vendor: PMWG > + impl version: 0x20b > + > +Ask for access permission to device#0: > + > +:: > + > + => scmi perm_dev 1 0 1 > + > +Reset configurations with all access permission settings retained: > + > +:: > + > + => scmi reset 1 0 > + > +Configuration > +- > + > +The scmi command is only available if CONFIG_CMD_SCMI=y. > +Default n because this command is mainly for debug purpose. > + > +Return value > + > + > +The return value ($?) is set to 0 if the operation succeeded, > +1 if the operation failed or -1 if the operation failed due to > +a syntax error. > + > +.. _`SCMI specification`: > https://developer.arm.com/documentation/den0056/e/?lang=en > -- > 2.41.0 >
RE: [PATCH v2 12/12] test: dm: add scmi command test
> From: AKASHI Takahiro > Sent: Wednesday, July 26, 2023 10:38 > > In this test, "scmi" command is tested against different sub-commands. > Please note that scmi command is for debug purpose and is not intended > in production system. > > Signed-off-by: AKASHI Takahiro > Reviewed-by: Simon Glass > --- > v2 > * use helper functions, removing direct uses of ops Reviewed-by: Etienne Carriere with patch on dm_test_scmi_base() squashed in patch 9/12. > --- > test/dm/scmi.c | 59 +++--- > 1 file changed, 56 insertions(+), 3 deletions(-) > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > index 41d46548f7fd..a3e61355088a 100644 > --- a/test/dm/scmi.c > +++ b/test/dm/scmi.c > @@ -134,9 +134,9 @@ static int dm_test_scmi_base(struct unit_test_state *uts) > ut_asserteq_str(priv->vendor, vendor); > > /* message attributes */ > - ret = scmi_protocol_message_attrs(base, > - SCMI_BASE_DISCOVER_SUB_VENDOR, > - &attributes); > + ret = scmi_base_protocol_message_attrs(base, > + SCMI_BASE_DISCOVER_SUB_VENDOR, > + &attributes); > ut_assertok(ret); > ut_assertok(attributes); > > @@ -204,6 +204,59 @@ static int dm_test_scmi_base(struct unit_test_state *uts) > > DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT); > > +static int dm_test_scmi_cmd(struct unit_test_state *uts) > +{ > + struct udevice *agent_dev; > + > + /* preparation */ > + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", > + &agent_dev)); > + ut_assertnonnull(agent_dev); > + > + /* scmi info */ > + ut_assertok(run_command("scmi info", 0)); > + > + ut_assert_nextline("SCMI device: scmi"); > + ut_assert_nextline(" protocol version: 0x2"); > + ut_assert_nextline(" # of agents: 2"); > + ut_assert_nextline(" 0: platform"); > + ut_assert_nextline(" > 1: OSPM"); > + ut_assert_nextline(" # of protocols: 3"); > + ut_assert_nextline(" Clock management"); > + ut_assert_nextline(" Reset domain management"); > + ut_assert_nextline(" Voltage domain management"); > + ut_assert_nextline(" vendor: U-Boot"); > + ut_assert_nextline(" sub vendor: Sandbox"); > + ut_assert_nextline(" impl version: 0x1"); > + > + ut_assert_console_end(); > + > + /* scmi perm_dev */ > + ut_assertok(run_command("scmi perm_dev 1 0 1", 0)); > + ut_assert_console_end(); > + > + ut_assert(run_command("scmi perm_dev 1 0 0", 0)); > + ut_assert_nextline("Denying access to device:0 failed (-13)"); > + ut_assert_console_end(); > + > + /* scmi perm_proto */ > + ut_assertok(run_command("scmi perm_proto 1 0 14 1", 0)); > + ut_assert_console_end(); > + > + ut_assert(run_command("scmi perm_proto 1 0 14 0", 0)); > + ut_assert_nextline("Denying access to protocol:0x14 on device:0 > failed (-13)"); > + ut_assert_console_end(); > + > + /* scmi reset */ > + ut_assert(run_command("scmi reset 1 1", 0)); > + ut_assert_nextline("Reset failed (-13)"); > + ut_assert_console_end(); > + > + return 0; > +} > + > +DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT); > + > static int dm_test_scmi_clocks(struct unit_test_state *uts) > { > struct sandbox_scmi_agent *agent; > -- > 2.41.0 >
Re: [RFC 1/3] firmware: scmi: add a check against availability of protocols
Hello Akashi-san, > From: AKASHI Takahiro > Sent: Friday, July 28, 2023 02:33 > Subject: [RFC 1/3] firmware: scmi: add a check against availability of > protocols > > Now that we have Base protocol support, we will be able to check if a given > protocol is really supported by the SCMI server (firmware). > > Signed-off-by: AKASHI Takahiro > --- Reviewed-by: Etienne Carriere > drivers/firmware/scmi/scmi_agent-uclass.c | 41 +-- > 1 file changed, 38 insertions(+), 3 deletions(-) > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index 91cb172f3005..9494dca95bca 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -44,6 +44,38 @@ static const struct error_code scmi_linux_errmap[] = { > */ > struct udevice *scmi_agent; > > +/** > + * scmi_protocol_is_supported - check availability of protocol > + * @dev: SCMI agent device > + * @proto_id: Identifier of protocol > + * > + * check if the protocol, @proto_id, is provided by the SCMI agent, > + * @dev. > + * > + * Return: 0 on success, error code otherwise > + */ > +static bool scmi_protocol_is_supported(struct udevice *dev, > + enum scmi_std_protocol proto_id) > +{ > + struct scmi_agent_priv *priv; > + int i; > + > + if (proto_id == SCMI_PROTOCOL_ID_BASE) > + return true; > + > + priv = dev_get_uclass_plat(dev); > + if (!priv) { > + dev_err(dev, "No priv data found\n"); > + return false; > + } > + > + for (i = 0; i < priv->num_protocols; i++) > + if (priv->protocols[i] == proto_id) > + return true; > + > + return false; > +} > + > struct udevice *scmi_get_protocol(struct udevice *dev, > enum scmi_std_protocol id) > { > @@ -372,15 +404,18 @@ static int scmi_bind_protocols(struct udevice *dev) > name = ofnode_get_name(node); > switch (protocol_id) { > case SCMI_PROTOCOL_ID_CLOCK: > - if (CONFIG_IS_ENABLED(CLK_SCMI)) > + if (CONFIG_IS_ENABLED(CLK_SCMI) && > + scmi_protocol_is_supported(dev, protocol_id)) > drv = DM_DRIVER_GET(scmi_clock); > break; > case SCMI_PROTOCOL_ID_RESET_DOMAIN: > - if (IS_ENABLED(CONFIG_RESET_SCMI)) > + if (IS_ENABLED(CONFIG_RESET_SCMI) && > + scmi_protocol_is_supported(dev, protocol_id)) > drv = DM_DRIVER_GET(scmi_reset_domain); > break; > case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: > - if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) { > + if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) && > + scmi_protocol_is_supported(dev, protocol_id)) { > node = ofnode_find_subnode(node, > "regulators"); > if (!ofnode_valid(node)) { > dev_err(dev, "no regulators node\n"); > -- > 2.41.0 > >
Re: [RFC 2/3] firmware: scmi: add PROTOCOL_VERSION support for existing protocols on sandbox
> From: AKASHI Takahiro > Sent: Friday, July 28, 2023 02:33 > Subject: [RFC 2/3] firmware: scmi: add PROTOCOL_VERSION support for existing > protocols on sandbox > > In the next patch, SCMI_PROTOCOL_VERSION support is added on the existing > SCMI protocols and the version check will be introduced. > To finish "ut dm scmi_[clocks|resets|voltage_domains]" tests, sandbox SCMI > agent should also implement/mimic this command. > > Signed-off-by: AKASHI Takahiro Aside the typos, inherited from previous patch series, the patch looks all good to me. Reviewed-by: Etienne Carriere preferrably with typos fixed. > --- > drivers/firmware/scmi/sandbox-scmi_agent.c | 80 ++ > 1 file changed, 80 insertions(+) > > diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c > b/drivers/firmware/scmi/sandbox-scmi_agent.c > index ab8afb01de40..a99fcb0ad4a9 100644 > --- a/drivers/firmware/scmi/sandbox-scmi_agent.c > +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c > @@ -43,6 +43,10 @@ > #define SANDBOX_SCMI_AGENT_NAME "OSPM" > #define SANDBOX_SCMI_PLATFORM_NAME "platform" > > +#define SANDBOX_SCMI_CLOCK_PROTOCOL_VERSION SCMI_CLOCK_PROTOCOL_VERSION > +#define SANDBOX_SCMI_RD_PROTOCOL_VERSION SCMI_RESETDOM_PROTOCOL_VERSION > +#define SANDBOX_SCMI_VOLTD_PROTOCOL_VERSION SCMI_VOLTDOM_PROTOCOL_VERSION > + > static u8 protocols[] = { > SCMI_PROTOCOL_ID_CLOCK, > SCMI_PROTOCOL_ID_RESET_DOMAIN, > @@ -440,6 +444,28 @@ static int > sandbox_scmi_base_reset_agent_configuration(struct udevice *dev, > > /* Clock Protocol */ > > +/** > + * sandbox_scmi_clock_protocol_version - implement SCMI_PROTOCOL_VERSION > + * @udevice: SCMI device Typos: s/udevice/udev/g here and for the 2 other inline description comments below. > + * @msg: SCMI message > + * > + * Implement SCMI_PROTOCOL_VERSION command. > + */ > +static int sandbox_scmi_clock_protocol_version(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct scmi_protocol_version_out *out = NULL; > + > + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) > + return -EINVAL; > + > + out = (struct scmi_protocol_version_out *)msg->out_msg; > + out->version = SANDBOX_SCMI_CLOCK_PROTOCOL_VERSION; > + out->status = SCMI_SUCCESS; > + > + return 0; > +} > + > static int sandbox_scmi_clock_protocol_attribs(struct udevice *dev, >struct scmi_msg *msg) > { > @@ -577,6 +603,30 @@ static int sandbox_scmi_clock_gate(struct udevice *dev, > struct scmi_msg *msg) > return 0; > } > > +/* Reset Domain Protocol */ > + > +/** > + * sandbox_scmi_rd_protocol_version - implement SCMI_PROTOCOL_VERSION > + * @udevice: SCMI device > + * @msg: SCMI message > + * > + * Implement SCMI_PROTOCOL_VERSION command. > + */ > +static int sandbox_scmi_rd_protocol_version(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct scmi_protocol_version_out *out = NULL; > + > + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) > + return -EINVAL; > + > + out = (struct scmi_protocol_version_out *)msg->out_msg; > + out->version = SANDBOX_SCMI_RD_PROTOCOL_VERSION; > + out->status = SCMI_SUCCESS; > + > + return 0; > +} > + > static int sandbox_scmi_rd_attribs(struct udevice *dev, struct scmi_msg *msg) > { > struct scmi_rd_attr_in *in = NULL; > @@ -647,6 +697,30 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, > struct scmi_msg *msg) > return 0; > } > > +/* Voltage Domain Protocol */ > + > +/** > + * sandbox_scmi_voltd_protocol_version - implement SCMI_PROTOCOL_VERSION > + * @udevice: SCMI device > + * @msg: SCMI message > + * > + * Implement SCMI_PROTOCOL_VERSION command. > + */ > +static int sandbox_scmi_voltd_protocol_version(struct udevice *dev, > + struct scmi_msg *msg) > +{ > + struct scmi_protocol_version_out *out = NULL; > + > + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) > + return -EINVAL; > + > + out = (struct scmi_protocol_version_out *)msg->out_msg; > + out->version = SANDBOX_SCMI_VOLTD_PROTOCOL_VERSION; > + out->status = SCMI_SUCCESS; > + > + return 0; > +} > + > static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg > *msg) > { > struct scmi_voltd_attr_i
Re: [RFC 3/3] firmware: scmi: add a sanity check against protocol version
> From: AKASHI Takahiro > Sent: Friday, July 28, 2023 02:33 > Subject: [RFC 3/3] firmware: scmi: add a sanity check against protocol version > > SCMI_PROTOCOL_VERSION is a mandatory command for all the SCMI protocols. > With this patch, this command is implemented on each protocol. > Then, we can assure that the feature set implemented by SCMI Server > (firmware) is compatible with U-Boot, that is, each protocol's version > must be equal to or higher than the one that U-Boot's corresponding driver > expects. > > Signed-off-by: AKASHI Takahiro > --- This change enforces some protocol versions that may not be reported by known open source scmi server implementations: scp-firmware, tf-a and op-tee. Latest scp-firwmare/op-tee/tf-a report the following verisons numbers: * base protocol : 0x2 all * clock protocol: 0x1 for scp-firwmare / 0x2 for op-tee and tf-a. * reset-dom: 0x1000 for all * voltage-dom: 0x1 for scp-firmware / 0x3 for op-tee / not used in tf-a. * power-dom: 0x2 for scp-firmware / 0x21000 for tf-a / not used in op-tee. Regarding the SCMI specification, these protocol versions evolve with the specification version: -- ---base -powerD --clock -resetD --voltD SCMI v1.0: 0x1 0x1 0x1 --- --- SCMI v2.0: 0x2 0x2 0x1 0x1 --- SCMI v3.0: 0x2 0x21000 0x1 0x2 0x1 SCMI v3.1: 0x2 0x3 0x3 0x3 0x2 SCMI v3.2: 0x2 0x3 0x3 0x3 0x2 This patch enforces the versions defined in SCMI v3.2. Being strict in protocol version is not ideal I think. BR, etienne > drivers/clk/clk_scmi.c | 6 ++ > drivers/power/regulator/scmi_regulator.c | 6 ++ > drivers/reset/reset-scmi.c | 14 +- > include/scmi_protocols.h | 6 ++ > 4 files changed, 31 insertions(+), 1 deletion(-) > > diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c > index 34a49363a51a..3591acb6d3a9 100644 > --- a/drivers/clk/clk_scmi.c > +++ b/drivers/clk/clk_scmi.c > @@ -138,12 +138,18 @@ static int scmi_clk_probe(struct udevice *dev) > { > struct clk *clk; > size_t num_clocks, i; > + u32 version; > int ret; > > ret = devm_scmi_of_get_channel(dev); > if (ret) > return ret; > > + ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_CLOCK, > + &version); > + if (ret || version < SCMI_CLOCK_PROTOCOL_VERSION) > + return -EINVAL; > + > if (!CONFIG_IS_ENABLED(CLK_CCF)) > return 0; > > diff --git a/drivers/power/regulator/scmi_regulator.c > b/drivers/power/regulator/scmi_regulator.c > index 08918b20872c..936768d0eeeb 100644 > --- a/drivers/power/regulator/scmi_regulator.c > +++ b/drivers/power/regulator/scmi_regulator.c > @@ -138,12 +138,18 @@ static int scmi_regulator_probe(struct udevice *dev) > .out_msg = (u8 *)&out, > .out_msg_sz = sizeof(out), > }; > + u32 version; > int ret; > > ret = devm_scmi_of_get_channel(dev); > if (ret) > return ret; > > + ret = scmi_generic_protocol_version(dev, > SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, > + &version); > + if (ret || version < SCMI_VOLTDOM_PROTOCOL_VERSION) > + return -EINVAL; > + > /* Check voltage domain is known from SCMI server */ > in.domain_id = pdata->domain_id; > > diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c > index b76711f0a8fb..dbd98dbdbc4f 100644 > --- a/drivers/reset/reset-scmi.c > +++ b/drivers/reset/reset-scmi.c > @@ -73,7 +73,19 @@ static const struct reset_ops scmi_reset_domain_ops = { > > static int scmi_reset_probe(struct udevice *dev) > { > - return devm_scmi_of_get_channel(dev); > + u32 version; > + int ret; > + > + ret = devm_scmi_of_get_channel(dev); > + if (ret) > + return ret; > + > + ret = scmi_generic_protocol_version(dev, > SCMI_PROTOCOL_ID_RESET_DOMAIN, > + &version); > + if (ret || version < SCMI_RESETDOM_PROTOCOL_VERSION) > + return -EINVAL; > + > + return 0; > } > > U_BOOT_DRIVER(scmi_reset_domain) = { > diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h > index 64fd740472b5..6ab16efd49cc 100644 > --- a/include/scmi_protocols.h > +++ b/include/scmi_protocols.h > @@ -398,6 +398,8 @@ int scmi_generic_protocol_version(struct udevice *dev, > * SCMI Clock Protocol > */ > > +#define SCMI_CLOCK_PROTOCOL_VERSION 0x2 TF-A and OP-TEE scmi servers report version 0x2 for clock protocol but SCP-firmware reports version 0x1: https://github.com/ARM-software/SCP-firmware/blob/master/module/scmi_clock/include/internal/scmi_clock.h#L16 > + > enum scmi_clock_message_id { > SCMI_CLOCK
Re: [PATCHv2 2/4] fwu: move meta-data management in core
Hello Jassi, On Sat, 3 Dec 2022 at 04:17, wrote: > > From: Jassi Brar > > Instead of each i/f having to implement their own meta-data verification > and storage, move the logic in common code. This simplifies the i/f code > much simpler and compact. > > Signed-off-by: Jassi Brar > --- > drivers/fwu-mdata/fwu-mdata-uclass.c | 34 +++ > include/fwu.h| 41 > lib/fwu_updates/fwu.c| 143 ++- > 3 files changed, 214 insertions(+), 4 deletions(-) > > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > b/drivers/fwu-mdata/fwu-mdata-uclass.c > index b477e9603f..e03773c584 100644 > --- a/drivers/fwu-mdata/fwu-mdata-uclass.c > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > @@ -16,6 +16,40 @@ > #include > #include > > +/** > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > + * > + * Return: 0 if OK, -ve on error > + */ > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->read_mdata) { > + log_debug("read_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->read_mdata(dev, mdata, primary); > +} > + > +/** > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > + * > + * Return: 0 if OK, -ve on error > + */ > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary) > +{ > + const struct fwu_mdata_ops *ops = device_get_ops(dev); > + > + if (!ops->write_mdata) { > + log_debug("write_mdata() method not defined\n"); > + return -ENOSYS; > + } > + > + return ops->write_mdata(dev, mdata, primary); > +} > + > /** > * fwu_get_mdata_part_num() - Get the FWU metadata partition numbers > * @dev: FWU metadata device > diff --git a/include/fwu.h b/include/fwu.h > index 0919ced812..1a700c9e6a 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -24,6 +24,26 @@ struct fwu_mdata_gpt_blk_priv { > * @update_mdata() - Update the FWU metadata copy > */ > struct fwu_mdata_ops { > + /** > +* read_mdata() - Populate the asked FWU metadata copy > +* @dev: FWU metadata device > +* @mdata: Copy of the FWU metadata > +* @primary: If primary or secondary copy of meta-data is to be read > +* > +* Return: 0 if OK, -ve on error > +*/ > + int (*read_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > + /** > +* write_mdata() - Write the given FWU metadata copy > +* @dev: FWU metadata device > +* @mdata: Copy of the FWU metadata > +* @primary: If primary or secondary copy of meta-data is to be > written > +* > +* Return: 0 if OK, -ve on error > +*/ > + int (*write_mdata)(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > /** > * check_mdata() - Check if the FWU metadata is valid > * @dev:FWU device > @@ -126,6 +146,27 @@ struct fwu_mdata_ops { > EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \ > 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8) > > +/** > + * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > + */ > +int fwu_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > +/** > + * fwu_write_mdata() - Wrapper around fwu_mdata_ops.write_mdata() > + */ > +int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > + > +/** > + * fwu_get_verified_mdata() - Read, verify and return the FWU metadata > + * > + * Read both the metadata copies from the storage media, verify their > checksum, > + * and ascertain that both copies match. If one of the copies has gone bad, > + * restore it from the good copy. > + * > + * Return: 0 if OK, -ve on error > +*/ > +int fwu_get_verified_mdata(struct fwu_mdata *mdata); > + > /** > * fwu_check_mdata_validity() - Check for validity of the FWU metadata copies > * > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 5313d07302..f17bd8ea63 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -15,13 +15,13 @@ > #include > #include > > +#include > + > +static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid > */ > +static struct udevice *g_dev; > static u8 in_trial; > static u8 boottime_check; > > -#include > -#include > -#include > - > enum { > IMAGE_ACCEPT_SET = 1, > IMAGE_ACCEPT_CLEAR, > @@ -161,6 +161,141 @@ static int fwu_get_image_type_id(u8 *image_index, > efi_guid_t *image_type_id) > return -ENOENT; > } > > +/** > + * fwu_sync_mdata() - Update given meta-data partition(s) with the copy > provided > + * @mdata: FWU metadata structure > + * @part: Bitmask of FWU metadata partitions to be written to > + * > + * Return: 0 if OK, -ve on erro
Re: [PATCHv2 5/4] fwu: rename fwu_get_verified_mdata to fwu_get_mdata
On Sat, 3 Dec 2022 at 04:28, wrote: > > From: Jassi Brar > > fwu_get_mdata() sounds more appropriate than fwu_get_verified_mdata() > > Signed-off-by: Jassi Brar > --- > Forgot to send this patch previously in v2 > cmd/fwu_mdata.c | 2 +- > include/fwu.h | 4 ++-- > lib/fwu_updates/fwu.c | 6 +++--- > 3 files changed, 6 insertions(+), 6 deletions(-) > Reviewed-by: Etienne Carriere > diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c > index 9b70340368..5ecda455df 100644 > --- a/cmd/fwu_mdata.c > +++ b/cmd/fwu_mdata.c > @@ -46,7 +46,7 @@ int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, > int ret = CMD_RET_SUCCESS, res; > struct fwu_mdata mdata; > > - res = fwu_get_verified_mdata(&mdata); > + res = fwu_get_mdata(&mdata); > if (res < 0) { > log_err("Unable to get valid FWU metadata\n"); > ret = CMD_RET_FAILURE; > diff --git a/include/fwu.h b/include/fwu.h > index 23bd97fe86..ea25aca2cd 100644 > --- a/include/fwu.h > +++ b/include/fwu.h > @@ -80,7 +80,7 @@ int fwu_read_mdata(struct udevice *dev, struct fwu_mdata > *mdata, bool primary); > int fwu_write_mdata(struct udevice *dev, struct fwu_mdata *mdata, bool > primary); > > /** > - * fwu_get_verified_mdata() - Read, verify and return the FWU metadata > + * fwu_get_mdata() - Read, verify and return the FWU metadata > * > * Read both the metadata copies from the storage media, verify their > checksum, > * and ascertain that both copies match. If one of the copies has gone bad, > @@ -88,7 +88,7 @@ int fwu_write_mdata(struct udevice *dev, struct fwu_mdata > *mdata, bool primary); > * > * Return: 0 if OK, -ve on error > */ > -int fwu_get_verified_mdata(struct fwu_mdata *mdata); > +int fwu_get_mdata(struct fwu_mdata *mdata); > > /** > * fwu_get_active_index() - Get active_index from the FWU metadata > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c > index 3d11d92fb9..77444ba2de 100644 > --- a/lib/fwu_updates/fwu.c > +++ b/lib/fwu_updates/fwu.c > @@ -191,7 +191,7 @@ static inline int mdata_crc_check(struct fwu_mdata *mdata) > } > > /** > - * fwu_get_verified_mdata() - Read, verify and return the FWU metadata > + * fwu_get_mdata() - Read, verify and return the FWU metadata > * > * Read both the metadata copies from the storage media, verify their > checksum, > * and ascertain that both copies match. If one of the copies has gone bad, > @@ -199,7 +199,7 @@ static inline int mdata_crc_check(struct fwu_mdata *mdata) > * > * Return: 0 if OK, -ve on error > */ > -int fwu_get_verified_mdata(struct fwu_mdata *mdata) > +int fwu_get_mdata(struct fwu_mdata *mdata) > { > int err; > bool pri_ok, sec_ok; > @@ -629,7 +629,7 @@ static int fwu_boottime_checks(void *ctx, struct event > *event) > return ret; > } > > - ret = fwu_get_verified_mdata(NULL); > + ret = fwu_get_mdata(NULL); > if (ret) { > log_debug("Unable to read meta-data\n"); > return ret; > -- > 2.34.1 >
Re: [PATCHv2 4/4] fwu: meta-data: switch to management by common code
On Sat, 3 Dec 2022 at 04:17, wrote: > > From: Jassi Brar > > The common code can now read, verify and fix meta-data copies > while exposing one consistent structure to users. > Only the .read_mdata() and .write_mdata() callbacks of fwu_mdata_ops > are needed. Get rid of .get_mdata() .update_mdata() .get_mdata_part_num() > .read_mdata_partition() and .write_mdata_partition() and also the > corresponding wrapper functions. > > Signed-off-by: Jassi Brar > --- > cmd/fwu_mdata.c | 17 +- > drivers/fwu-mdata/fwu-mdata-uclass.c | 165 --- > drivers/fwu-mdata/gpt_blk.c | 124 +- > include/fwu.h| 199 --- > lib/fwu_updates/fwu.c| 235 --- > 5 files changed, 38 insertions(+), 702 deletions(-) > Reviewed-by: Etienne Carriere > diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c > index f04af27de6..9b70340368 100644 > --- a/cmd/fwu_mdata.c > +++ b/cmd/fwu_mdata.c > @@ -43,23 +43,10 @@ static void print_mdata(struct fwu_mdata *mdata) > int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag, > int argc, char * const argv[]) > { > - struct udevice *dev; > int ret = CMD_RET_SUCCESS, res; > - struct fwu_mdata mdata = { 0 }; > + struct fwu_mdata mdata; > > - if (uclass_get_device(UCLASS_FWU_MDATA, 0, &dev) || !dev) { > - log_err("Unable to get FWU metadata device\n"); > - return CMD_RET_FAILURE; > - } > - > - res = fwu_check_mdata_validity(); > - if (res < 0) { > - log_err("FWU Metadata check failed\n"); > - ret = CMD_RET_FAILURE; > - goto out; > - } > - > - res = fwu_get_mdata(dev, &mdata); > + res = fwu_get_verified_mdata(&mdata); > if (res < 0) { > log_err("Unable to get valid FWU metadata\n"); > ret = CMD_RET_FAILURE; > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c > b/drivers/fwu-mdata/fwu-mdata-uclass.c > index e03773c584..0a8edaaa41 100644 > --- a/drivers/fwu-mdata/fwu-mdata-uclass.c > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c > @@ -14,7 +14,6 @@ > > #include > #include > -#include > > /** > * fwu_read_mdata() - Wrapper around fwu_mdata_ops.read_mdata() > @@ -50,170 +49,6 @@ int fwu_write_mdata(struct udevice *dev, struct fwu_mdata > *mdata, bool primary) > return ops->write_mdata(dev, mdata, primary); > } > > -/** > - * fwu_get_mdata_part_num() - Get the FWU metadata partition numbers > - * @dev: FWU metadata device > - * @mdata_parts: array for storing the metadata partition numbers > - * > - * Get the partition numbers on the storage device on which the > - * FWU metadata is stored. Two partition numbers will be returned. > - * > - * Return: 0 if OK, -ve on error > - * > - */ > -int fwu_get_mdata_part_num(struct udevice *dev, uint *mdata_parts) > -{ > - const struct fwu_mdata_ops *ops = device_get_ops(dev); > - > - if (!ops->get_mdata_part_num) { > - log_debug("get_mdata_part_num() method not defined\n"); > - return -ENOSYS; > - } > - > - return ops->get_mdata_part_num(dev, mdata_parts); > -} > - > -/** > - * fwu_read_mdata_partition() - Read the FWU metadata from a partition > - * @dev: FWU metadata device > - * @mdata: Copy of the FWU metadata > - * @part_num: Partition number from which FWU metadata is to be read > - * > - * Read the FWU metadata from the specified partition number > - * > - * Return: 0 if OK, -ve on error > - * > - */ > -int fwu_read_mdata_partition(struct udevice *dev, struct fwu_mdata *mdata, > -uint part_num) > -{ > - const struct fwu_mdata_ops *ops = device_get_ops(dev); > - > - if (!ops->read_mdata_partition) { > - log_debug("read_mdata_partition() method not defined\n"); > - return -ENOSYS; > - } > - > - return ops->read_mdata_partition(dev, mdata, part_num); > -} > - > -/** > - * fwu_write_mdata_partition() - Write the FWU metadata to a partition > - * @dev: FWU metadata device > - * @mdata: Copy of the FWU metadata > - * @part_num: Partition number to which FWU metadata is to be written > - * > - * Write the FWU metadata to the specified partition number > - * > - * Return: 0 if OK, -ve on error > - * > - */ > -int fwu_write_mdata_partition(struct udevice *dev, struct fwu_mdata *mdata, > - uint part_num) &
Re: [PATCHv2 3/4] fwu: gpt: implement read_mdata and write_mdata callbacks
Hi Jassi, On Thu, 22 Dec 2022 at 13:59, Ilias Apalodimas wrote: > > Hi Jassi, > > On Fri, Dec 02, 2022 at 09:17:12PM -0600, jassisinghb...@gmail.com wrote: > > From: Jassi Brar > > > > Moving towards using common code for meta-data management, > > implement the read/write mdata hooks. > > > > Signed-off-by: Jassi Brar > > --- > > drivers/fwu-mdata/gpt_blk.c | 40 +++-- > > 1 file changed, 38 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c > > index 28f5d23e1e..35239c0a4f 100644 > > --- a/drivers/fwu-mdata/gpt_blk.c > > +++ b/drivers/fwu-mdata/gpt_blk.c > > @@ -222,7 +222,7 @@ static int fwu_gpt_read_mdata_partition(struct udevice > > *dev, > > struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > > > > return gpt_read_write_mdata(dev_get_uclass_plat(priv->blk_dev), > > - mdata, MDATA_READ, part_num); > > +mdata, MDATA_READ, part_num); > > I assume this was by mistake? > I agree. Discard this change. > > } > > > > static int fwu_gpt_write_mdata_partition(struct udevice *dev, > > @@ -231,7 +231,7 @@ static int fwu_gpt_write_mdata_partition(struct udevice > > *dev, > > struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > > > > return gpt_read_write_mdata(dev_get_uclass_plat(priv->blk_dev), > > - mdata, MDATA_WRITE, part_num); > > +mdata, MDATA_WRITE, part_num); > > ditto > > > } > > > > static int fwu_get_mdata_device(struct udevice *dev, struct udevice > > **mdata_dev) > > @@ -272,7 +272,43 @@ static int fwu_mdata_gpt_blk_probe(struct udevice *dev) > > return 0; > > } > > > > +static int fwu_gpt_read_mdata(struct udevice *dev, struct fwu_mdata *mdata, > > + bool primary) > > +{ > > + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > > + struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); > > + int ret; > > + > > + ret = gpt_get_mdata_partitions(desc); > > + if (ret < 0) { > > + log_debug("Error getting the FWU metadata partitions\n"); > > + return -ENOENT; > > + } > > + > > + return gpt_read_write_mdata(desc, mdata, MDATA_READ, > > +primary ? g_mdata_part[0] : > > g_mdata_part[1]); > > +} > > + > > +static int fwu_gpt_write_mdata(struct udevice *dev, struct fwu_mdata > > *mdata, > > + bool primary) > > +{ > > + struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev); > > + struct blk_desc *desc = dev_get_uclass_plat(priv->blk_dev); > > + int ret; > > + > > + ret = gpt_get_mdata_partitions(desc); > > + if (ret < 0) { > > + log_debug("Error getting the FWU metadata partitions\n"); > > + return -ENOENT; > > + } > > + > > + return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, > > +primary ? g_mdata_part[0] : > > g_mdata_part[1]); > > +} > > + > > static const struct fwu_mdata_ops fwu_gpt_blk_ops = { > > + .read_mdata = fwu_gpt_read_mdata, > > + .write_mdata = fwu_gpt_write_mdata, > > .get_mdata = fwu_gpt_get_mdata, > > .update_mdata = fwu_gpt_update_mdata, > > .get_mdata_part_num = fwu_gpt_get_mdata_partitions, > > -- > > 2.34.1 > > > > > Other than that > Reviewed-by: Ilias Apalodimas > Reviewed-by: Etienne Carriere with Ilias' comments addressed.
Re: [PATCH 3/3] bootm: Support boot measurement
Hello Eddie and all, On Tue, 3 Jan 2023 at 21:42, Eddie James wrote: > > Add a configuration option to measure the boot through the bootm > function. > > Signed-off-by: Eddie James > --- > boot/bootm.c| 53 + > cmd/bootm.c | 2 ++ > common/Kconfig | 6 ++ > include/image.h | 1 + > 4 files changed, 62 insertions(+) > > diff --git a/boot/bootm.c b/boot/bootm.c > index a4c0870c0f..7f64d79035 100644 > --- a/boot/bootm.c > +++ b/boot/bootm.c > @@ -22,6 +22,9 @@ > #include > #include > #include > +#if defined(CONFIG_MEASURED_BOOT) > +#include > +#endif > #if defined(CONFIG_CMD_USB) > #include > #endif > @@ -713,6 +716,56 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int > argc, > if (!ret && (states & BOOTM_STATE_FINDOTHER)) > ret = bootm_find_other(cmdtp, flag, argc, argv); > > +#if defined(CONFIG_MEASURED_BOOT) > + if (!ret && (states & BOOTM_STATE_MEASURE)) { > + void *initrd_buf; > + void *image_buf; > + const char *s; > + u32 rd_len; > + > + ret = tcg2_measurement_init(); > + if (ret) > + goto measure_err; > + > + image_buf = map_sysmem(images->os.image_start, > + images->os.image_len); > + ret = tcg2_measure_data(8, images->os.image_len, image_buf, > + EV_COMPACT_HASH, strlen("linux") + 1, > + (u8 *)"linux"); > + if (ret) > + goto unmap_image; > + > + rd_len = images->rd_end - images->rd_start; > + initrd_buf = map_sysmem(images->rd_start, rd_len); > + ret = tcg2_measure_data(8, rd_len, initrd_buf, > EV_COMPACT_HASH, > + strlen("initrd") + 1, (u8 *)"initrd"); > + if (ret) > + goto unmap_initrd; > + > + ret = tcg2_measure_data(9, images->ft_len, > + (u8 *)images->ft_addr, > + EV_TABLE_OF_DEVICES, strlen("dts") + > 1, > + (u8 *)"dts"); This unconditionally measures DTB content but maybe there are information that may differ at each boot as a random MAC address or an ASLR seed. Do you think something should condition measurement of the passed DTB as proposed using a config switch in [1]? [1] https://lore.kernel.org/all/20221207151110.529106-1-etienne.carri...@linaro.org/ Regards, Etienne > + if (ret) > + goto unmap_initrd; > + > + s = env_get("bootargs"); > + if (!s) > + s = ""; > + tcg2_measure_data(1, strlen(s) + 1, (u8 *)s, > + EV_PLATFORM_CONFIG_FLAGS, strlen(s) + 1, > + (u8 *)s); > + > +unmap_initrd: > + unmap_sysmem(initrd_buf); > +unmap_image: > + unmap_sysmem(image_buf); > + tcg2_measurement_term(); > +measure_err: > + ret = 0; > + } > +#endif > + > /* Load the OS */ > if (!ret && (states & BOOTM_STATE_LOADOS)) { > iflag = bootm_disable_interrupts(); > diff --git a/cmd/bootm.c b/cmd/bootm.c > index 37c2af96e0..0c4a713e02 100644 > --- a/cmd/bootm.c > +++ b/cmd/bootm.c > @@ -161,6 +161,8 @@ int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, > char *const argv[]) > BOOTM_STATE_OS_GO; > if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH)) > states |= BOOTM_STATE_RAMDISK; > + if (IS_ENABLED(CONFIG_MEASURED_BOOT)) > + states |= BOOTM_STATE_MEASURE; > if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS)) > states |= BOOTM_STATE_OS_CMDLINE; > ret = do_bootm_states(cmdtp, flag, argc, argv, states, &images, 1); > diff --git a/common/Kconfig b/common/Kconfig > index 21434c5cf1..57ef68e4f3 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -799,6 +799,12 @@ config AVB_BUF_SIZE > > endif # AVB_VERIFY > > +config MEASURED_BOOT > + bool "Measure the boot to TPM and event log" > + depends on HASH && TPM_V2 > + help > + This option enables measurement of the boot process. > + > config SCP03 > bool "Build SCP03 - Secure Channel Protocol O3 - controls" > depends on OPTEE || SANDBOX > diff --git a/include/image.h b/include/image.h > index 6f21dafba8..b00803eeac 100644 > --- a/include/image.h > +++ b/include/image.h > @@ -406,6 +406,7 @@ struct bootm_headers { > #define BOOTM_STATE_OS_FAKE_GO 0x0200 /* 'Almost' run the OS */ > #define BOOTM_STATE_OS_GO 0x0400 > #define BOOTM_STATE_PRE_LOAD 0x0800 > +#define BOOTM_STATE_MEASURE0x1000 > int
Re: [PATCHv2 1/4] fwu: gpt: use cached meta-data partition numbers
On Mon, 2 Jan 2023 at 18:15, Jassi Brar wrote: > > On Thu, 22 Dec 2022 at 06:45, Ilias Apalodimas > wrote: > > > > On Fri, Dec 02, 2022 at 09:16:51PM -0600, jassisinghb...@gmail.com wrote: > > > From: Jassi Brar > > > > > > Use cached values and avoid parsing and scanning through partitions > > > everytime for meta-data partitions because they can't change after bootup. > > > > > > Acked-by: Etienne Carriere > > > Signed-off-by: Jassi Brar > > > --- > > > drivers/fwu-mdata/gpt_blk.c | 43 + > > > 1 file changed, 24 insertions(+), 19 deletions(-) > > > > > > diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c > > > index d35ce49c5c..28f5d23e1e 100644 > > > --- a/drivers/fwu-mdata/gpt_blk.c > > > +++ b/drivers/fwu-mdata/gpt_blk.c > > > @@ -24,8 +24,9 @@ enum { > > > MDATA_WRITE, > > > }; > > > > > > -static int gpt_get_mdata_partitions(struct blk_desc *desc, > > > - uint mdata_parts[2]) > > > +static uint g_mdata_part[2]; /* = {0, 0} to check against uninit parts */ > > > + > > > +static int gpt_get_mdata_partitions(struct blk_desc *desc) > > > { > > > int i, ret; > > > u32 nparts; > > > @@ -33,18 +34,19 @@ static int gpt_get_mdata_partitions(struct blk_desc > > > *desc, > > > struct disk_partition info; > > > const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID; > > > > > > + /* if primary and secondary partitions already found */ > > > + if (g_mdata_part[0] && g_mdata_part[1]) > > > + return 0; > > > + > > > nparts = 0; > > > - for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) { > > > + for (i = 1; i < MAX_SEARCH_PARTITIONS && nparts < 2; i++) { > > > if (part_get_info(desc, i, &info)) > > > continue; > > > uuid_str_to_bin(info.type_guid, part_type_guid.b, > > > UUID_STR_FORMAT_GUID); > > > > > > - if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) { > > > - if (nparts < 2) > > > - mdata_parts[nparts] = i; > > > - ++nparts; > > > - } > > > + if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) > > > + g_mdata_part[nparts++] = i; > > > > The reason the 'if (nparts < 2)' was outside the main loop was to show > > errors in case the user defined more than two partitions. Can we keep it > > like that or am I the only being paranoid here? > > > I am not sure if that is an 'error', because FWU only cares about the > first two partitions it comes across. There is no way other ones could > impact the operations. > And if fwu code is responsible for correctness of the setup, there are > things that we already don't care about. So maybe we keep the code > simple? > > cheers. I agree with Jassi. We can keep code simple here. The embedded code is not designed to valide DT content but to use it. Etienne
[PATCH 1/2] tee: optee: don't fail on services enumeration failure
Change optee probe function to only warn when service enumeration sequence fails instead of reporting an optee driver probe failure. Indeed U-Boot can still use OP-TEE even if some OP-TEE services are not discovered. Fixes: 94ccfb78a4d6 ("drivers: tee: optee: discover OP-TEE services") Signed-off-by: Etienne Carriere --- drivers/tee/optee/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 9a9b697e91..5308dd58ce 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -841,7 +841,7 @@ static int optee_probe(struct udevice *dev) if (IS_ENABLED(CONFIG_OPTEE_SERVICE_DISCOVERY)) { ret = bind_service_drivers(dev); if (ret) - return ret; + dev_warn(dev, "optee service enumeration failed: %d\n", ret); } else if (IS_ENABLED(CONFIG_RNG_OPTEE)) { /* * Discovery of TAs on the TEE bus is not supported in U-Boot: -- 2.25.1
[PATCH 2/2] tee: optee: don't enumerate services if there ain't any
Change optee driver service enumeration to not enumerate (and allocate a zero sized shared memory buffer) when OP-TEE reports that there is no service to enumerate. This change fixes an existing issue that occurs when the such zero sized shared memory buffer allocated from malloc() has a physical address of offset 0 of a physical 4kB page. In such case, OP-TEE secure world refuses to register the zero-sized shared memory area and makes U-Boot optee service enumeration to fail. Fixes: 94ccfb78a4d6 ("drivers: tee: optee: discover OP-TEE services") Signed-off-by: Etienne Carriere --- drivers/tee/optee/core.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 5308dd58ce..47f845cffe 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -139,6 +139,11 @@ static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t *coun if (ret) return ret; + if (!shm_size) { + *count = 0; + return 0; + } + ret = tee_shm_alloc(dev, shm_size, 0, shm); if (ret) { dev_err(dev, "Failed to allocated shared memory: %d\n", ret); @@ -185,14 +190,15 @@ static int bind_service_drivers(struct udevice *dev) ret = enum_services(dev, &service_list, &service_count, tee_sess, PTA_CMD_GET_DEVICES); - if (!ret) + if (!ret && service_count) ret = bind_service_list(dev, service_list, service_count); tee_shm_free(service_list); + service_list = NULL; ret2 = enum_services(dev, &service_list, &service_count, tee_sess, PTA_CMD_GET_DEVICES_SUPP); - if (!ret2) + if (!ret2 && service_count) ret2 = bind_service_list(dev, service_list, service_count); tee_shm_free(service_list); -- 2.25.1
Re: [PATCH v5 3/4] drivers: tee: sandbox: add rpc test ta emulation
Hi Igor, On Wed, 20 Jan 2021 at 18:56, Igor Opaniuk wrote: > > From: Igor Opaniuk > > This adds support for RPC test trusted application emulation, which > permits to test reverse RPC calls to TEE supplicant. Currently it covers > requests to the I2C bus from TEE. > > Signed-off-by: Igor Opaniuk > Reviewed-by: Simon Glass > --- > > (no changes since v1) > > drivers/tee/Makefile| 2 + > drivers/tee/optee/Kconfig | 9 ++ > drivers/tee/sandbox.c | 143 +++- > include/tee/optee_ta_rpc_test.h | 28 +++ > 4 files changed, 178 insertions(+), 4 deletions(-) > create mode 100644 include/tee/optee_ta_rpc_test.h > > diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile > index 5c8ffdbce8..ff844195ae 100644 > --- a/drivers/tee/Makefile > +++ b/drivers/tee/Makefile > @@ -2,5 +2,7 @@ > > obj-y += tee-uclass.o > obj-$(CONFIG_SANDBOX) += sandbox.o > +obj-$(CONFIG_OPTEE_TA_RPC_TEST) += optee/supplicant.o > +obj-$(CONFIG_OPTEE_TA_RPC_TEST) += optee/i2c.o I think this line should move to drivers/tee/optee/Makefile for consistency. > obj-$(CONFIG_OPTEE) += optee/ > obj-y += broadcom/ > diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig > index d489834df9..65622f30b1 100644 > --- a/drivers/tee/optee/Kconfig > +++ b/drivers/tee/optee/Kconfig > @@ -22,6 +22,15 @@ config OPTEE_TA_AVB > The TA can support the "avb" subcommands "read_rb", "write"rb" > and "is_unlocked". > > +config OPTEE_TA_RPC_TEST > + bool "Support RPC TEST TA" > + depends on SANDBOX_TEE > + default y > + help > + Enables support for RPC test trusted application emulation, which > + permits to test reverse RPC calls to TEE supplicant. Should > + be used only in sandbox env. > + > endmenu > > endif > diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c > index e1ba027fd6..d075701b4e 100644 > --- a/drivers/tee/sandbox.c > +++ b/drivers/tee/sandbox.c > @@ -7,11 +7,15 @@ > #include > #include > #include > +#include > + > +#include "optee/optee_msg.h" > +#include "optee/optee_private.h" > > /* > * The sandbox tee driver tries to emulate a generic Trusted Exectution > - * Environment (TEE) with the Trusted Application (TA) OPTEE_TA_AVB > - * available. > + * Environment (TEE) with the Trusted Applications (TA) OPTEE_TA_AVB and > + * OPTEE_TA_RPC_TEST available. > */ > > static const u32 pstorage_max = 16; > @@ -32,7 +36,38 @@ struct ta_entry { >struct tee_param *params); > }; > > -#ifdef CONFIG_OPTEE_TA_AVB > +static int get_msg_arg(struct udevice *dev, uint num_params, > + struct tee_shm **shmp, struct optee_msg_arg **msg_arg) > +{ > + int rc; > + struct optee_msg_arg *ma; > + > + rc = __tee_shm_add(dev, OPTEE_MSG_NONCONTIG_PAGE_SIZE, NULL, > + OPTEE_MSG_GET_ARG_SIZE(num_params), TEE_SHM_ALLOC, > + shmp); > + if (rc) > + return rc; > + > + ma = (*shmp)->addr; > + memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); > + ma->num_params = num_params; > + *msg_arg = ma; > + > + return 0; > +} > + > +void *optee_alloc_and_init_page_list(void *buf, ulong len, > +u64 *phys_buf_ptr) > +{ > + /* > +* An empty stub is added just to fix linking issues. > +* This function isn't supposed to be called in sandbox > +* setup, otherwise replace this with a proper > +* implementation from optee/core.c > +*/ > + return NULL; > +} > + > static u32 get_attr(uint n, uint num_params, struct tee_param *params) > { > if (n >= num_params) > @@ -63,6 +98,7 @@ bad_params: > return TEE_ERROR_BAD_PARAMETERS; > } > > +#ifdef CONFIG_OPTEE_TA_AVB > static u32 ta_avb_open_session(struct udevice *dev, uint num_params, >struct tee_param *params) > { > @@ -214,7 +250,100 @@ static u32 ta_avb_invoke_func(struct udevice *dev, u32 > func, uint num_params, > return TEE_ERROR_NOT_SUPPORTED; > } > } > -#endif /*OPTEE_TA_AVB*/ > +#endif /* OPTEE_TA_AVB */ > + > +#ifdef CONFIG_OPTEE_TA_RPC_TEST > +static u32 ta_rpc_test_open_session(struct udevice *dev, uint num_params, > + struct tee_param *params) > +{ > + /* > +* We don't expect additional parameters when opening a session to > +* this TA. > +*/ > + return check_params(TEE_PARAM_ATTR_TYPE_NONE, > TEE_PARAM_ATTR_TYPE_NONE, > + TEE_PARAM_ATTR_TYPE_NONE, > TEE_PARAM_ATTR_TYPE_NONE, > + num_params, params); > +} > + > +static void fill_i2c_rpc_params(struct optee_msg_arg *msg_arg, u64 bus_num, > + u64 chip_addr, u64 op, > + struct tee_param_memref memref) > +{ > + ms
Re: [PATCH v5 4/4] test: dm: tee: extend with RPC test
Hello Igor, On Wed, 20 Jan 2021 at 18:56, Igor Opaniuk wrote: > > From: Igor Opaniuk > > Extend existing DM tee tests adding test coverage for reverse RPC calls. > Currently this commit only adds tests for I2C requests from TEE driver > to TEE supplicant, for instance reading/writing data to emulated i2c > eeprom defines in standard sandbox test device tree > (arch/sandbox/dts/test.dtb): > > => i2c bus > Bus 0: i2c@0 (active 0) >2c: eeprom@2c, offset len 1, flags 0 >... > > Running TEE tests: > => ut dm tee > Test: dm_test_tee: tee.c > Test: dm_test_tee: tee.c (flat tree) > Failures: 0 > > Signed-off-by: Igor Opaniuk > Reviewed-by: Simon Glass > > --- > > (no changes since v1) > > test/dm/tee.c | 107 +++--- > 1 file changed, 102 insertions(+), 5 deletions(-) > > diff --git a/test/dm/tee.c b/test/dm/tee.c > index ddbdcfb0cf..51ffb4e4a9 100644 > --- a/test/dm/tee.c > +++ b/test/dm/tee.c > @@ -13,11 +13,12 @@ > #include > #include > #include > +#include > > -static int open_session(struct udevice *dev, u32 *session) > +static int open_session(struct udevice *dev, u32 *session, > + struct tee_optee_ta_uuid uuid) maybe pass a pointer to the uuid. or maybe not, uuid is only 16 bytes > { > struct tee_open_session_arg arg; > - const struct tee_optee_ta_uuid uuid = TA_AVB_UUID; > int rc; > > memset(&arg, 0, sizeof(arg)); > @@ -32,7 +33,7 @@ static int open_session(struct udevice *dev, u32 *session) > return 0; > } > > -static int invoke_func(struct udevice *dev, u32 session) > +static int invoke_func_avb(struct udevice *dev, u32 session) > { > struct tee_param param = { .attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT }; > struct tee_invoke_arg arg; > @@ -47,6 +48,47 @@ static int invoke_func(struct udevice *dev, u32 session) > return 0; > } > > +static int invoke_func_rpc_test(struct udevice *dev, u32 session, > + u64 op, u64 busnum, u64 chip_addr, > + u8 *buf, size_t buf_size) > +{ > + struct tee_param param[2]; > + struct tee_invoke_arg arg; > + struct tee_shm *shm_buf; > + int rc; > + > + memset(&arg, 0, sizeof(arg)); > + arg.session = session; > + arg.func = op; > + > + rc = tee_shm_alloc(dev, buf_size, > + TEE_SHM_ALLOC, &shm_buf); > + if (rc) > + return rc; > + > + if (op == TA_RPC_TEST_CMD_I2C_WRITE) > + memcpy(shm_buf->addr, buf, buf_size); > + > + memset(param, 0, sizeof(param)); > + param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; > + param[0].u.value.a = busnum; > + param[0].u.value.b = chip_addr; > + param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT; > + param[1].u.memref.shm = shm_buf; > + param[1].u.memref.size = buf_size; > + > + if (tee_invoke_func(dev, &arg, 2, param) || arg.ret) { > + goto out; > + rc = -1; Looks like those lines shall be swapped! > + } > + > + if (op == TA_RPC_TEST_CMD_I2C_READ) > + memcpy(buf, shm_buf->addr, buf_size); > +out: > + tee_shm_free(shm_buf); > + return rc; > +} > + > static int match(struct tee_version_data *vers, const void *data) > { > return vers->gen_caps & TEE_GEN_CAP_GP; > @@ -62,6 +104,7 @@ static int test_tee(struct unit_test_state *uts, struct > test_tee_vars *vars) > struct tee_version_data vers; > struct udevice *dev; > struct sandbox_tee_state *state; > + struct tee_optee_ta_uuid avb_uuid = TA_AVB_UUID; > u32 session = 0; > int rc; > u8 data[128]; > @@ -71,11 +114,11 @@ static int test_tee(struct unit_test_state *uts, struct > test_tee_vars *vars) > state = dev_get_priv(dev); > ut_assert(!state->session); > > - rc = open_session(dev, &session); > + rc = open_session(dev, &session, avb_uuid); > ut_assert(!rc); > ut_assert(session == state->session); > > - rc = invoke_func(dev, session); > + rc = invoke_func_avb(dev, session); > ut_assert(!rc); > > rc = tee_close_session(dev, session); > @@ -103,11 +146,65 @@ static int test_tee(struct unit_test_state *uts, struct > test_tee_vars *vars) > return 0; > } > > +#define I2C_BUF_SIZE 64 > + > +static int test_tee_rpc(struct unit_test_state *uts) > +{ > + struct tee_version_data vers; > + struct udevice *dev; > + struct sandbox_tee_state *state; > + struct tee_optee_ta_uuid rpc_test_uuid = TA_RPC_TEST_UUID; > + u32 session = 0; > + int rc; > + > + char *test_str = "Test string"; > + u8 data[I2C_BUF_SIZE] = {0}; > + u8 data_from_eeprom[I2C_BUF_SIZE] = {0}; > + > + /* Use sandbox I2C EEPROM emulation; bus: 0, chip: 0x2c */ > + u64 bus = 0; > + u64 chip = 0x2c; > + >
Re: [PATCH 3/4] clk: add clock driver for SCMI agents
Hello Simon and all, On Sun, 26 Jul 2020 at 16:54, Simon Glass wrote: > > Hi Etienne, > > On Fri, 17 Jul 2020 at 09:43, Etienne Carriere > wrote: > > > > This change introduces a clock driver for SCMI agent devices. When > > SCMI agent and SCMI clock drivers are enabled, SCMI agent binds a > > clock device for each SCMI clock protocol devices enabled in the FDT. > > > > SCMI clock driver is embedded upon CONFIG_CLK_SCMI=y. If enabled, > > CONFIG_SCMI_AGENT is also enabled. > > > > SCMI Clock protocol is defined in the SCMI specification [1]. > > > > Links: [1] > > https://developer.arm.com/architectures/system-architectures/software-standards/scmi > > That doesn't seem to work for me (404 error) I think that Arm site was broken when you tried. Works fine and this seems to be the official Arm URL for the SCMI specification. > > > Signed-off-by: Etienne Carriere > > --- > > > > drivers/clk/Kconfig | 8 +++ > > drivers/clk/Makefile| 1 + > > drivers/clk/clk_scmi.c | 152 > > drivers/firmware/scmi.c | 3 + > > 4 files changed, 164 insertions(+) > > create mode 100644 drivers/clk/clk_scmi.c > > > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig > > index 82cb1874e19..234d6035202 100644 > > --- a/drivers/clk/Kconfig > > +++ b/drivers/clk/Kconfig > > @@ -152,6 +152,14 @@ config CLK_CDCE9XX > >Enable the clock synthesizer driver for CDCE913/925/937/949 > >series of chips. > > > > +config CLK_SCMI > > + bool "Enable SCMI clock driver" > > + select SCMI_FIRMWARE > > perhaps 'depends on' would be better? Ok > > > + help > > + Enable this option if you want to support clock devices exposed > > + by a SCMI agent based on SCMI clock protocol communication > > + with a SCMI server. > > + > > source "drivers/clk/analogbits/Kconfig" > > source "drivers/clk/at91/Kconfig" > > source "drivers/clk/exynos/Kconfig" > > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile > > index d9119545810..76bba77d1f0 100644 > > --- a/drivers/clk/Makefile > > +++ b/drivers/clk/Makefile > > @@ -31,6 +31,7 @@ obj-$(CONFIG_CLK_K210) += kendryte/ > > obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o > > obj-$(CONFIG_CLK_OWL) += owl/ > > obj-$(CONFIG_CLK_RENESAS) += renesas/ > > +obj-$(CONFIG_CLK_SCMI) += clk_scmi.o > > obj-$(CONFIG_CLK_SIFIVE) += sifive/ > > obj-$(CONFIG_ARCH_SUNXI) += sunxi/ > > obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o > > diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c > > new file mode 100644 > > index 000..efe64a6a38f > > --- /dev/null > > +++ b/drivers/clk/clk_scmi.c > > @@ -0,0 +1,152 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (C) 2019-2020 Linaro Limited > > + */ > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +enum scmi_clock_message_id { > > + SCMI_CLOCK_RATE_SET = 0x5, > > + SCMI_CLOCK_RATE_GET = 0x6, > > + SCMI_CLOCK_CONFIG_SET = 0x7, > > +}; > > + > > +#define SCMI_CLK_RATE_ASYNC_NOTIFY BIT(0) > > +#define SCMI_CLK_RATE_ASYNC_NORESP (BIT(0) | BIT(1)) > > +#define SCMI_CLK_RATE_ROUND_DOWN 0 > > +#define SCMI_CLK_RATE_ROUND_UP BIT(2) > > +#define SCMI_CLK_RATE_ROUND_CLOSESTBIT(3) > > + > > +struct scmi_clk_state_in { > > + u32 clock_id; > > + u32 attributes; > > +}; > > + > > +struct scmi_clk_state_out { > > + s32 status; > > +}; > > + > > +static int scmi_clk_gate(struct clk *clk, int enable) > > +{ > > + struct scmi_clk_state_in in = { > > + .clock_id = clk->id, > > + .attributes = enable, > > + }; > > + struct scmi_clk_state_out out; > > + struct scmi_msg scmi_msg = { > > + .protocol_id = SCMI_PROTOCOL_ID_CLOCK, > > + .message_id = SCMI_CLOCK_CONFIG_SET, > > + .in_msg = (u8 *)&in, > > + .in_msg_sz = sizeof(in), > > + .out_msg = (u8 *)&out, > > + .out_msg_sz = sizeof(out), > > + }; > > + int rc; > > Again please use 'ret'. Sure, will do. > > > + > > + rc = scmi_send_and_process_msg(clk->dev->parent, &scmi_msg
[PATCH v2 1/4] firmware: add new driver for SCMI firmwares
This change introduces SCMI agent driver in U-Boot in the firmware U-class. SCMI agent driver is designed for platforms that embed a SCMI server in a firmware hosted for example by a companion co-processor or the secure world of the executing processor. SCMI protocols allow an SCMI agent to discover and access external resources as clock, reset controllers and many more. SCMI agent and server communicate following the SCMI specification [1]. SCMI agent complies with the DT bindings defined in the Linux kernel source tree regarding SCMI agent description since v5.8-rc1. These bindings describe 2 supported message transport layer: using mailbox uclass devices or using Arm SMC invocation instruction. Both use a piece or shared memory for message data exchange. In the current state, the SCMI agent driver does not bind to any SCMI protocol to a U-Boot device driver. Former changes will implement dedicated driver (i.e. an SCMI clock driver or an SCMI reset controller driver) and add bind supported SCMI protocols in scmi_agent_bind(). Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v2: - Fix CONFIG_SCMI_FIRMWARE description with explicit SCMI reference. - Move struct, enum and macro definitions at source file top and add inline comment description for the structures and local functions. - Replace rc with ret as return value local variable label. - Use explicit return 0 on successful return paths. - Replace EINVAL with more accurate error numbers. - Use dev_read_u32() instead of ofnode_read_u32(dev_ofnode(), ...). - Use memcpy_toio()/memcpy_fromio() when copying message payload to/from IO memory. - Embed mailbox transport resources upon CONFIG_DM_MAILBOX and SMCCC transport resources upon CONFIG_ARM_SMCCC. Note: review comments on defining a uclass and sandbox for SCMI transport drivers are NOT addressed in this v2. Main issue is that there is no driver/device defined for SCMI transport layer as well as and no defined compatible ID in the SCMI DT bindings documentation. --- drivers/firmware/Kconfig | 20 ++ drivers/firmware/Makefile | 1 + drivers/firmware/scmi.c | 490 ++ include/scmi.h| 82 +++ 4 files changed, 593 insertions(+) create mode 100644 drivers/firmware/scmi.c create mode 100644 include/scmi.h diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index b70a206355..4d3cd5c6f2 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -1,6 +1,26 @@ config FIRMWARE bool "Enable Firmware driver support" +config SCMI_FIRMWARE + bool "Enable SCMI support" + select FIRMWARE + select OF_TRANSLATE + depends on DM_MAILBOX || ARM_SMCCC + help + System Control and Management Interface (SCMI) is a communication + protocol that defines standard interfaces for power, performance + and system management. The SCMI specification is available at + https://developer.arm.com/architectures/system-architectures/software-standards/scmi + + An SCMI agent communicates with a related SCMI server firmware + located in another sub-system, as a companion micro controller + or a companion host in the CPU system. + + Communications between agent (client) and the SCMI server are + based on message exchange. Messages can be exchange over tranport + channels as a mailbox device or an Arm SMCCC service with some + piece of identified shared memory. + config SPL_FIRMWARE bool "Enable Firmware driver support in SPL" depends on FIRMWARE diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index a0c250a473..9d16055510 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -2,4 +2,5 @@ obj-$(CONFIG_FIRMWARE) += firmware-uclass.o obj-$(CONFIG_$(SPL_)ARM_PSCI_FW) += psci.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_SANDBOX) += firmware-sandbox.o +obj-$(CONFIG_SCMI_FIRMWARE)+= scmi.o obj-$(CONFIG_ZYNQMP_FIRMWARE) += firmware-zynqmp.o diff --git a/drivers/firmware/scmi.c b/drivers/firmware/scmi.c new file mode 100644 index 00..264f3d99c8 --- /dev/null +++ b/drivers/firmware/scmi.c @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (C) 2019-2020 Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_US_10MS1 + +/** + * enum scmi_transport_channel - Supported SCMI transport layers + */ +enum scmi_transport_channel {
[PATCH v2 4/4] reset: add reset controller driver for SCMI agents
This change introduces a reset controller driver for SCMI agent devices. When SCMI agent and SCMI reset domain drivers are enabled, SCMI agent binds a reset controller device for each SCMI reset domain protocol devices enabled in the FDT. SCMI reset driver is embedded upon CONFIG_RESET_SCMI=y. If enabled, CONFIG_SCMI_AGENT is also enabled. SCMI Reset Domain protocol is defined in the SCMI specification [1]. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v2: - Change reset request() method to at least check the reset domain exists by sending a SCMI RESET_DOMAIN_ATTRIBUTE message. - Add inline description for the several structures. - Patch v1 R-b tag not applied since the above changes in this v2. --- drivers/firmware/scmi.c| 3 + drivers/reset/Kconfig | 8 +++ drivers/reset/Makefile | 1 + drivers/reset/reset-scmi.c | 143 + 4 files changed, 155 insertions(+) create mode 100644 drivers/reset/reset-scmi.c diff --git a/drivers/firmware/scmi.c b/drivers/firmware/scmi.c index cddfa0bbc2..07a2b0f986 100644 --- a/drivers/firmware/scmi.c +++ b/drivers/firmware/scmi.c @@ -460,6 +460,9 @@ static int scmi_bind(struct udevice *dev) case SCMI_PROTOCOL_ID_CLOCK: drv = DM_GET_DRIVER(scmi_clock); break; + case SCMI_PROTOCOL_ID_RESET_DOMAIN: + drv = DM_GET_DRIVER(scmi_reset_domain); + break; default: dev_info(dev, "Ignore unsupported SCMI protocol %u\n", protocol_id); diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 253902ff57..ee5be0bc2f 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -173,4 +173,12 @@ config RESET_RASPBERRYPI relevant. This driver provides a reset controller capable of interfacing with RPi4's co-processor and model these firmware initialization routines as reset lines. + +config RESET_SCMI + bool "Enable SCMI reset domain driver" + select SCMI_FIRMWARE + help + Enable this option if you want to support reset controller + devices exposed by a SCMI agent based on SCMI reset domain + protocol communication with a SCMI server. endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 3c7f066ae3..625ec7168e 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_SIFIVE) += reset-sifive.o obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o +obj-$(CONFIG_RESET_SCMI) += reset-scmi.o diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c new file mode 100644 index 00..e8dabc9751 --- /dev/null +++ b/drivers/reset/reset-scmi.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-2020 Linaro Limited + */ +#include +#include +#include +#include +#include +#include + +#define SCMI_RD_NAME_LEN 16 + +#define SCMI_RD_RESET_FLAG_ASSERT BIT(1) +#define SCMI_RD_RESET_FLAG_DEASSERT0 + +enum scmi_reset_domain_message_id { + SCMI_RESET_DOMAIN_ATTRIBUTES = 0x3, + SCMI_RESET_DOMAIN_RESET = 0x4, +}; + +/** + * struct scmi_rd_attr_in - Payload for RESET_DOMAIN_ATTRIBUTES message + * @domain_id: SCMI reset domain ID + */ +struct scmi_rd_attr_in { + u32 domain_id; +}; + +/** + * struct scmi_rd_attr_out - Payload for RESET_DOMAIN_ATTRIBUTES response + * @status:SCMI command status + * @attributes:Retrieved attributes of the reset domain + * @latency: Reset cycle max lantency + * @name: Reset domain name + */ +struct scmi_rd_attr_out { + s32 status; + u32 attributes; + u32 latency; + char name[SCMI_RD_NAME_LEN]; +}; + +/** + * struct scmi_rd_reset_in - Message payload for RESET command + * @domain_id: SCMI reset domain ID + * @flags: Flags for the reset request + * @reset_state: Reset target state + */ +struct scmi_rd_reset_in { + u32 domain_id; + u32 flags; + u32 reset_state; +}; + +/** + * struct scmi_rd_reset_out - Response payload for RESET command + * @status:SCMI command status + */ +struct scmi_rd_reset_out { + s32 status; +}; + +static int scmi_reset_set_state(struct reset_ctl *rst, int assert_not_deassert) +{ + struct scmi_rd_reset_in in = { + .domain_id = rst->id, + .flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : +SCMI_RD_RESET_FLAG_DEASSERT, + .reset_state = 0, + }; + struct scmi_rd_reset_out out; + struct scmi_msg scmi_msg = {
[PATCH v2 3/4] clk: add clock driver for SCMI agents
This change introduces a clock driver for SCMI agent devices. When SCMI agent and SCMI clock drivers are enabled, SCMI agent binds a clock device for each SCMI clock protocol devices enabled in the FDT. SCMI clock driver is embedded upon CONFIG_CLK_SCMI=y. If enabled, CONFIG_SCMI_AGENT is also enabled. SCMI Clock protocol is defined in the SCMI specification [1]. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Lukasz Majewski Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v2: - CONFIG_CLK_SCMI depends on CONFIG_SCMI_FIRMWARE instead of selecting CONFIG_SCMI_FIRMWARE. - Add inline comment description for structures and moves them to source file top. Add/fixup some functions inline description comments. - Replace rc with ret as return value local variable label. - Fix scmi_clk_get_rate() return value to propagate error number. - Fix scmi_clk_set_rate() to request synchronous rate set operation: drop flag SCMI_CLK_RATE_ASYNC_NORESP in the SCMI message payload. - Fix scmi_clk_set_rate() return value to return clock effective rate on success. --- drivers/clk/Kconfig | 8 ++ drivers/clk/Makefile| 1 + drivers/clk/clk_scmi.c | 186 drivers/firmware/scmi.c | 3 + 4 files changed, 198 insertions(+) create mode 100644 drivers/clk/clk_scmi.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6003e140b5..4dfbad7986 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -159,6 +159,14 @@ config CLK_CDCE9XX Enable the clock synthesizer driver for CDCE913/925/937/949 series of chips. +config CLK_SCMI + bool "Enable SCMI clock driver" + depends on SCMI_FIRMWARE + help + Enable this option if you want to support clock devices exposed + by a SCMI agent based on SCMI clock protocol communication + with a SCMI server. + source "drivers/clk/analogbits/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/exynos/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index cda4b4b605..d1e295ac7c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ +obj-$(CONFIG_CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c new file mode 100644 index 00..6abeb1a4c4 --- /dev/null +++ b/drivers/clk/clk_scmi.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-2020 Linaro Limited + */ +#include +#include +#include +#include +#include + +enum scmi_clock_message_id { + SCMI_CLOCK_RATE_SET = 0x5, + SCMI_CLOCK_RATE_GET = 0x6, + SCMI_CLOCK_CONFIG_SET = 0x7, +}; + +#define SCMI_CLK_RATE_ASYNC_NOTIFY BIT(0) +#define SCMI_CLK_RATE_ASYNC_NORESP (BIT(0) | BIT(1)) +#define SCMI_CLK_RATE_ROUND_DOWN 0 +#define SCMI_CLK_RATE_ROUND_UP BIT(2) +#define SCMI_CLK_RATE_ROUND_CLOSESTBIT(3) + +/** + * struct scmi_clk_state_in - Message payload for CLOCK_CONFIG_SET command + * @clock_id: SCMI clock ID + * @attributes:Attributes of the targets clock state + */ +struct scmi_clk_state_in { + u32 clock_id; + u32 attributes; +}; + +/** + * struct scmi_clk_state_out - Response payload for CLOCK_CONFIG_SET command + * @status:SCMI command status + */ +struct scmi_clk_state_out { + s32 status; +}; + +/** + * struct scmi_clk_state_in - Message payload for CLOCK_RATE_GET command + * @clock_id: SCMI clock ID + * @attributes:Attributes of the targets clock state + */ +struct scmi_clk_rate_get_in { + u32 clock_id; +}; + +/** + * struct scmi_clk_rate_get_out - Response payload for CLOCK_RATE_GET command + * @status:SCMI command status + * @rate_lsb: 32bit LSB of the clock rate in Hertz + * @rate_msb: 32bit MSB of the clock rate in Hertz + */ +struct scmi_clk_rate_get_out { + s32 status; + u32 rate_lsb; + u32 rate_msb; +}; + +/** + * struct scmi_clk_state_in - Message payload for CLOCK_RATE_SET command + * @clock_id: SCMI clock ID + * @flags: Flags for the clock rate set request + * @rate_lsb: 32bit LSB of the clock rate in Hertz + * @rate_msb: 32bit MSB of the clock rate in Hertz + */ +struct scmi_clk_rate_set_in { + u32 clock_id; + u32 flags; + u32 rate_lsb; + u32 rate_msb; +}; + +/** + * struct scmi_clk_rate_set_out - Response payload for CLOCK_RATE_SET command + * @status:SCMI command status + */ +struct scmi_clk_rate_set_out { + s32 status; +}; + +static int scmi_clk_gate(struct clk *clk, int enable) +{ + struct scmi_clk_state_in in
[PATCH v2 2/4] dt-bindings: arm: SCMI bindings documentation
Dump SCMI DT bindings documentation from Linux kernel source tree v5.8-rc1. Signed-off-by: Etienne Carriere Reviewed-by: Simon Glass --- Changes in v2: - No change but added R-b tag. - Yet a question: do we need to add this binding doc in U-Boot since already existing in Linux DT bindings docs? Related to review comment https://www.mail-archive.com/u-boot@lists.denx.de/msg377725.html --- doc/device-tree-bindings/arm/arm,scmi.txt | 197 ++ 1 file changed, 197 insertions(+) create mode 100644 doc/device-tree-bindings/arm/arm,scmi.txt diff --git a/doc/device-tree-bindings/arm/arm,scmi.txt b/doc/device-tree-bindings/arm/arm,scmi.txt new file mode 100644 index 00..1f293ea24c --- /dev/null +++ b/doc/device-tree-bindings/arm/arm,scmi.txt @@ -0,0 +1,197 @@ +System Control and Management Interface (SCMI) Message Protocol +-- + +The SCMI is intended to allow agents such as OSPM to manage various functions +that are provided by the hardware platform it is running on, including power +and performance functions. + +This binding is intended to define the interface the firmware implementing +the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control +and Management Interface Platform Design Document")[0] provide for OSPM in +the device tree. + +Required properties: + +The scmi node with the following properties shall be under the /firmware/ node. + +- compatible : shall be "arm,scmi" or "arm,scmi-smc" for smc/hvc transports +- mboxes: List of phandle and mailbox channel specifiers. It should contain + exactly one or two mailboxes, one for transmitting messages("tx") + and another optional for receiving the notifications("rx") if + supported. +- shmem : List of phandle pointing to the shared memory(SHM) area as per + generic mailbox client binding. +- #address-cells : should be '1' if the device has sub-nodes, maps to + protocol identifier for a given sub-node. +- #size-cells : should be '0' as 'reg' property doesn't have any size + associated with it. +- arm,smc-id : SMC id required when using smc or hvc transports + +Optional properties: + +- mbox-names: shall be "tx" or "rx" depending on mboxes entries. + +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details +about the generic mailbox controller and client driver bindings. + +The mailbox is the only permitted method of calling the SCMI firmware. +Mailbox doorbell is used as a mechanism to alert the presence of a +messages and/or notification. + +Each protocol supported shall have a sub-node with corresponding compatible +as described in the following sections. If the platform supports dedicated +communication channel for a particular protocol, the 3 properties namely: +mboxes, mbox-names and shmem shall be present in the sub-node corresponding +to that protocol. + +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol + + +This binding uses the common clock binding[1]. + +Required properties: +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands. + +Power domain bindings for the power domains based on SCMI Message Protocol + + +This binding for the SCMI power domain providers uses the generic power +domain binding[2]. + +Required properties: + - #power-domain-cells : Should be 1. Contains the device or the power +domain ID value used by SCMI commands. + +Sensor bindings for the sensors based on SCMI Message Protocol +-- +SCMI provides an API to access the various sensors on the SoC. + +Required properties: +- #thermal-sensor-cells: should be set to 1. This property follows the +thermal device tree bindings[3]. + +Valid cell values are raw identifiers (Sensor ID) +as used by the firmware. Refer to platform details +for your implementation for the IDs to use. + +Reset signal bindings for the reset domains based on SCMI Message Protocol + + +This binding for the SCMI reset domain providers uses the generic reset +signal binding[5]. + +Required properties: + - #reset-cells : Should be 1. Contains the reset domain ID value used + by SCMI commands. + +SRAM and Shared Memory for SCMI +--- + +A small area of SRAM is reserved for SCMI communication between application +processors and SCP. + +The properties should follow the generic mmio-sram description found in [4] + +Each sub-node represents the reserved area for SCMI. + +Required sub-nod
Re: [PATCH v2 1/4] firmware: add new driver for SCMI firmwares
Hello Sudeep, On Tue, 18 Aug 2020 at 17:44, Etienne Carriere wrote: > > This change introduces SCMI agent driver in U-Boot in the firmware > U-class. > (...) > --- a/drivers/firmware/Kconfig > +++ b/drivers/firmware/Kconfig > @@ -1,6 +1,26 @@ > config FIRMWARE > bool "Enable Firmware driver support" > > +config SCMI_FIRMWARE > + bool "Enable SCMI support" > + select FIRMWARE > + select OF_TRANSLATE > + depends on DM_MAILBOX || ARM_SMCCC > + help > + System Control and Management Interface (SCMI) is a communication > + protocol that defines standard interfaces for power, performance > + and system management. The SCMI specification is available at > + > https://developer.arm.com/architectures/system-architectures/software-standards/scmi You suggested https://developer.arm.com/documentation/den0056/latest. It is shorter and points straight to the spec document whereas this link is used above points to more generic info about SCMI among which one can find the spec doc. Maybe I should change to the link you suggested. > + > + An SCMI agent communicates with a related SCMI server firmware > + located in another sub-system, as a companion micro controller > + or a companion host in the CPU system. > + > + Communications between agent (client) and the SCMI server are > + based on message exchange. Messages can be exchange over tranport Typo here: s/tranport/transport/ > + channels as a mailbox device or an Arm SMCCC service with some > + piece of identified shared memory. > + > config SPL_FIRMWARE > bool "Enable Firmware driver support in SPL" > depends on FIRMWARE
Re: [PATCH v2 1/4] firmware: add new driver for SCMI firmwares
Hello Simon, > > This change introduces SCMI agent driver in U-Boot in the firmware > > U-class. > > (...) > > Changes in v2: > > (...) > > > > Note: review comments on defining a uclass and sandbox for SCMI > > transport drivers are NOT addressed in this v2. Main issue is that > > there is no driver/device defined for SCMI transport layer as well as > > and no defined compatible ID in the SCMI DT bindings documentation. > > I'd still like to see this. You can define an API with a header file. > It is certainly easier if the DT binding can cover the transport type > with a separate subnode. The bindings are already defined for scmi (ref is the Linux kernel source tree) and there is no sub-node currently defined for the scmi driver transport configuration. It's done through the compatible property and dedicated optional properties. I think changing the scmi DT binding is a bit out of the scope of my patch series :) > But that doesn't stop you creating a uclass > for the transport. It will also allow you to create a sandbox impl so > you can add a test for this code. Ok, thanks, I understand. > > Also the two interfaces should really be in separate files rather than > using #ifdefs, I think. I'll send a v3 with the implementation over several source files and the requested uclass/sandbox. I think I'll create sub-directory drivers/firmware/scmi/ for the source files. Thanks again for the feedback on this v2. Regards, Etienne > > > --- > > drivers/firmware/Kconfig | 20 ++ > > drivers/firmware/Makefile | 1 + > > drivers/firmware/scmi.c | 490 ++ > > include/scmi.h| 82 +++ > > 4 files changed, 593 insertions(+) > > create mode 100644 drivers/firmware/scmi.c > > create mode 100644 include/scmi.h > > > > Regards, > Simon
Re: [PATCH v3 1/3] fdtdec: optionally add property no-map to created reserved memory node
Hello Heinrich, On Tue, 25 Aug 2020 at 16:50, Heinrich Schuchardt wrote: > > On 25.08.20 13:42, Patrice Chotard wrote: > > From: Etienne Carriere > > > > Add boolean input argument @no_map to helper function > > fdtdec_add_reserved_memory() to add "no-map" property for an added > > reserved memory node. This is needed for example when the reserved > > memory relates to secure memory that the dear Linux kernel shall > > not even map unless what non-secure world speculative accesses of the > > This sentence needs rework. Do you mean "to avoid non-secure world > accesses of the CPU that might reveal the secure-world memory"? > > Is there any evidence that mapping memory as reserved can lead to an > information leak and that not mapping solves the problem? Is there a CVE > for it? There should not be issues related to revealing secure world memory. Such memory is likely to be protected by a hardware firewall. Issues are rather due to CPU speculative execution that could emit read requests to such firewalled memory areas. These read request would infringe the firewall policy which would likely report a system error and would possibly panic the system. By not mapping such memory areas, speculative reads are discarded before leaving the CPU, at least on Arm architecture. Note that "no-map" property is also used by Linux to prevent inconsistent kernel mapping for memories that are mapped non-cached at runtime by some specific driver. Such memory must be not mapped by the kernel static memory mapping. Ok, let's rephrase this commit log. Proposal for the patchset v4: I hope it looks better: | fdtdec: optionally add property no-map to created reserved memory node | | Add boolean input argument @no_map to helper function | fdtdec_add_reserved_memory() to add or not "no-map" property | for an added reserved memory node. | | Property no-map is used by the Linux kernel to not not map memory | in its static memory mapping. It is needed for example for the| | consistency of system non-cached memory and to prevent speculative | accesses to some firewalled memory. | | No functional change. A later change will update to OPTEE library to | add no-map property to OP-TEE reserved memory nodes. | | Signed-off-by: (...) > > CPU can violate the memory firmware configuration. > > Most Linux distributions boot via EFI. > > In U-Boot's UEFI sub-system we pass reserved memory as > EFI_RESERVED_MEMORY_TYPE in the memory map to Linux. See function > efi_carve_out_dt_rsv(). We do not consider the no-map attribute in the > device-tree. > > Does the Linux kernel care about this no-map attribute in the > device-tree if we are booting via UEFI? Sorry I lack experience and knowledge on how Linux relies on UEFI versus DT to describe the system memory. I think the EFI_RESERVED_MEMORY_TYPE should consider such reserved memory attributes, but I'm far from knowing how UEFI should handle that. This is quite a late answer from me. Since your post I saw there are discussion in this area: https://lists.linaro.org/pipermail/boot-architecture/2020-September/001389.html > > > > > No function change. A later change will update to OPTEE library to > > add no-map property to OP-TEE reserved memory nodes. > > > > Signed-off-by: Etienne Carriere > > Signed-off-by: Patrice Chotard > > --- > > > > (no changes since v2) > > > > Changes in v2: > >- fix dm fdtdec test and arch/riscv/lib/fdt_fixup.c with > >fdtdec_add_reserved_memory() new parameter > > > > arch/riscv/lib/fdt_fixup.c | 2 +- > > include/fdtdec.h | 5 +++-- > > lib/fdtdec.c | 10 -- > > lib/optee/optee.c | 2 +- > > test/dm/fdtdec.c | 6 +++--- > > 5 files changed, 16 insertions(+), 9 deletions(-) > > > > diff --git a/arch/riscv/lib/fdt_fixup.c b/arch/riscv/lib/fdt_fixup.c > > index 5b2420243f..d02062fd5b 100644 > > --- a/arch/riscv/lib/fdt_fixup.c > > +++ b/arch/riscv/lib/fdt_fixup.c > > @@ -75,7 +75,7 @@ int riscv_fdt_copy_resv_mem_node(const void *src, void > > *dst) > > pmp_mem.start = addr; > > pmp_mem.end = addr + size - 1; > > err = fdtdec_add_reserved_memory(dst, basename, &pmp_mem, > > - &phandle); > > + &phandle, false); > > I guess in a future patch we would want to set nomap=true here too as > this is the memory reserved by the secure execution environment (e.g. > OpenSBI). I think so, yes, but I would prefer RISCV maintainers to comment on that. Best regards, Etienne > > Best regards > > Heinrich > > > if (err < 0 && err != -FDT_ERR_EXISTS) { > > log_err("failed to add reserved memory: %d\n", err); > > return err; > > diff --git a/include/fdtdec.h b/include/fdtdec.h > > index bc79389260..f127c7d386 100644 > > --- a/include/fdtdec.h > > +++ b/include/fdtdec.h > > (...)
[PATCH v3 1/8] firmware: add SCMI agent uclass
This change introduces SCMI agent uclass to interact with a firmware using the SCMI protocols [1]. SCMI agent uclass currently supports a single method to request processing of the SCMI message by an identified server. A SCMI message is made of a byte payload associated to a protocol ID and a message ID, all defined by the SCMI specification [1]. On return from process_msg() method, the caller gets the service response. SCMI agent uclass defines a post bind generic sequence for all devices. The sequence binds all the SCMI protocols listed in the FDT for that SCMI agent device. Currently none, but later change will introduce protocols. This change implements a simple sandbox device for the SCMI agent uclass. The sandbox nicely answers SCMI_NOT_SUPPORTED to SCMI messages. To prepare for further test support, the sandbox exposes a architecture function for test application to read the sandbox emulated devices state. Currently supports 2 SCMI agents, identified by an ID in the FDT device name. The simplistic DM test does nothing yet. SCMI agent uclass is designed for platforms that embed a SCMI server in a firmware hosted somewhere, for example in a companion co-processor or in the secure world of the executing processor. SCMI protocols allow an SCMI agent to discover and access external resources as clock, reset controllers and more. SCMI agent and server communicate following the SCMI specification [1]. This SCMI agent implementation complies with the DT bindings defined in the Linux kernel source tree regarding SCMI agent description since v5.8. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: - Address comments about adding a new uclass and some sandbox test from v2 in https://patchwork.ozlabs.org/project/uboot/list/?series=196253 - New directory drivers/firmware/scmi/. The path mimics Linux kernel source tree for the equivalent driver. - Split scmi.h (patch v2) into scmi_protocols.h, scmi_agent.h and scmi_agent-uclass.h. - Create new uclass UCLASS_SCMI_AGENT. - Introduce a simple sandbox on that agent. Mailbox and smccc agents are moved to specific commits in the series. Changes in v2: - Fix CONFIG_SCMI_FIRMWARE description with explicit SCMI reference. - Move struct, enum and macro definitions at source file top and add inline comment description for the structures and local functions. - Replace rc with ret as return value local variable label. - Use explicit return 0 on successful return paths. - Replace EINVAL with more accurate error numbers. - Use dev_read_u32() instead of ofnode_read_u32(dev_ofnode(), ...). - Use memcpy_toio()/memcpy_fromio() when copying message payload to/from IO memory. - Embed mailbox transport resources upon CONFIG_DM_MAILBOX and SMCCC transport resources upon CONFIG_ARM_SMCCC. Note: review comments on defining a uclass and sandbox for SCMI transport drivers are NOT addressed in this v2. Main issue is that there is no driver/device defined for SCMI transport layer as well as and no defined compatible ID in the SCMI DT bindings documentation. --- arch/sandbox/dts/test.dts | 16 +++ arch/sandbox/include/asm/scmi_test.h | 43 ++ configs/sandbox_defconfig | 2 + drivers/firmware/Kconfig | 2 + drivers/firmware/Makefile | 1 + drivers/firmware/scmi/Kconfig | 17 +++ drivers/firmware/scmi/Makefile | 2 + drivers/firmware/scmi/sandbox-scmi_agent.c | 147 + drivers/firmware/scmi/scmi_agent-uclass.c | 107 +++ include/dm/uclass-id.h | 1 + include/scmi_agent-uclass.h| 24 include/scmi_agent.h | 68 ++ include/scmi_protocols.h | 41 ++ test/dm/Makefile | 1 + test/dm/scmi.c | 38 ++ 15 files changed, 510 insertions(+) create mode 100644 arch/sandbox/include/asm/scmi_test.h create mode 100644 drivers/firmware/scmi/Kconfig create mode 100644 drivers/firmware/scmi/Makefile create mode 100644 drivers/firmware/scmi/sandbox-scmi_agent.c create mode 100644 drivers/firmware/scmi/scmi_agent-uclass.c create mode 100644 include/scmi_agent-uclass.h create mode 100644 include/scmi_agent.h create mode 100644 include/scmi_protocols.h create mode 100644 test/dm/scmi.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9f45c48e4e..dd3b43885e 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -356,6 +356,22 @@ sandbox_firmware: sandbox-firmware { compatible = "sandbox,firmware"; }; + + sandbox-scmi-agent@0 { + compatible = "sandbox,scmi-agent"; +
[PATCH v3 2/8] firmware: scmi: mailbox/smt agent device
This change implements a mailbox transport using SMT format for SCMI exchanges. This implementation follows the Linux kernel and SCP-firmware [1] as references implementation for SCMI message processing using SMT format for communication channel meta-data. Use of mailboxes in SCMI FDT bindings are defined in the Linux kernel DT bindings since v4.17. Links: [1] https://github.com/ARM-software/SCP-firmware Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: - This is a followup of the SCMI agent patches posted in https://patchwork.ozlabs.org/project/uboot/list/?series=196253 The v3 splits commits and introduces a new uclass as requested. - This patch implements the same mailbox SCMI agent proposed in v2 but split over few source files. --- drivers/firmware/scmi/Kconfig | 6 +- drivers/firmware/scmi/Makefile| 2 + drivers/firmware/scmi/mailbox_agent.c | 107 drivers/firmware/scmi/smt.c | 139 ++ drivers/firmware/scmi/smt.h | 86 5 files changed, 338 insertions(+), 2 deletions(-) create mode 100644 drivers/firmware/scmi/mailbox_agent.c create mode 100644 drivers/firmware/scmi/smt.c create mode 100644 drivers/firmware/scmi/smt.h diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index 57e2ebbe42..c501bf4943 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -2,7 +2,7 @@ config SCMI_FIRMWARE bool "Enable SCMI support" select FIRMWARE select OF_TRANSLATE - depends on SANDBOX + depends on SANDBOX || DM_MAILBOX help System Control and Management Interface (SCMI) is a communication protocol that defines standard interfaces for power, performance @@ -14,4 +14,6 @@ config SCMI_FIRMWARE or a companion host in the CPU system. Communications between agent (client) and the SCMI server are - based on message exchange. + based on message exchange. Messages can be exchange over tranport + channels as a mailbox device with some piece of identified shared + memory. diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index 336ea1f2a3..d22f53efe7 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -1,2 +1,4 @@ obj-y += scmi_agent-uclass.o +obj-y += smt.o +obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o diff --git a/drivers/firmware/scmi/mailbox_agent.c b/drivers/firmware/scmi/mailbox_agent.c new file mode 100644 index 00..9a7b0a5858 --- /dev/null +++ b/drivers/firmware/scmi/mailbox_agent.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smt.h" + +#define TIMEOUT_US_10MS1 + +/** + * struct scmi_mbox_channel - Description of an SCMI mailbox transport + * @smt: Shared memory buffer + * @mbox: Mailbox channel description + * @timeout_us:Timeout in microseconds for the mailbox transfer + */ +struct scmi_mbox_channel { + struct scmi_smt smt; + struct mbox_chan mbox; + ulong timeout_us; +}; + +static struct scmi_mbox_channel *scmi_mbox_get_priv(struct udevice *dev) +{ + return (struct scmi_mbox_channel *)dev_get_priv(dev); +} + +static int scmi_mbox_process_msg(struct udevice *dev, struct scmi_msg *msg) +{ + struct scmi_mbox_channel *chan = scmi_mbox_get_priv(dev); + int ret; + + ret = scmi_write_msg_to_smt(dev, &chan->smt, msg); + if (ret) + return ret; + + /* Give shm addr to mbox in case it is meaningful */ + ret = mbox_send(&chan->mbox, chan->smt.buf); + if (ret) { + dev_err(dev, "Message send failed: %d\n", ret); + goto out; + } + + /* Receive the response */ + ret = mbox_recv(&chan->mbox, chan->smt.buf, chan->timeout_us); + if (ret) { + dev_err(dev, "Response failed: %d, abort\n", ret); + goto out; + } + + ret = scmi_read_resp_from_smt(dev, &chan->smt, msg); + +out: + scmi_clear_smt_channel(&chan->smt); + + return ret; +} + +int scmi_mbox_probe(struct udevice *dev) +{ + struct scmi_mbox_channel *chan = scmi_mbox_get_priv(dev); + int ret; + + chan->timeout_us = TIMEOUT_US_10MS; + + ret = mbox_get_by_index(dev, 0, &chan->mbox); + if (ret) { + dev_err(dev, "Failed to find mailbox: %d\n", ret); + goto out; + } + + ret = scmi_dt_get_smt_buffer(dev, &chan->smt); + if (ret) + dev_er
[PATCH v3 4/8] dt-bindings: arm: SCMI bindings documentation
Dump SCMI DT bindings documentation from Linux kernel source tree v5.8-rc1. Signed-off-by: Etienne Carriere Reviewed-by: Simon Glass --- No change in v3. Changes in v2: - No change but added R-b tag. - Yet a question: do we need to add this binding doc in U-Boot since already existing in Linux DT bindings docs? Related to review comment https://www.mail-archive.com/u-boot@lists.denx.de/msg377725.html --- doc/device-tree-bindings/arm/arm,scmi.txt | 197 ++ 1 file changed, 197 insertions(+) create mode 100644 doc/device-tree-bindings/arm/arm,scmi.txt diff --git a/doc/device-tree-bindings/arm/arm,scmi.txt b/doc/device-tree-bindings/arm/arm,scmi.txt new file mode 100644 index 00..1f293ea24c --- /dev/null +++ b/doc/device-tree-bindings/arm/arm,scmi.txt @@ -0,0 +1,197 @@ +System Control and Management Interface (SCMI) Message Protocol +-- + +The SCMI is intended to allow agents such as OSPM to manage various functions +that are provided by the hardware platform it is running on, including power +and performance functions. + +This binding is intended to define the interface the firmware implementing +the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control +and Management Interface Platform Design Document")[0] provide for OSPM in +the device tree. + +Required properties: + +The scmi node with the following properties shall be under the /firmware/ node. + +- compatible : shall be "arm,scmi" or "arm,scmi-smc" for smc/hvc transports +- mboxes: List of phandle and mailbox channel specifiers. It should contain + exactly one or two mailboxes, one for transmitting messages("tx") + and another optional for receiving the notifications("rx") if + supported. +- shmem : List of phandle pointing to the shared memory(SHM) area as per + generic mailbox client binding. +- #address-cells : should be '1' if the device has sub-nodes, maps to + protocol identifier for a given sub-node. +- #size-cells : should be '0' as 'reg' property doesn't have any size + associated with it. +- arm,smc-id : SMC id required when using smc or hvc transports + +Optional properties: + +- mbox-names: shall be "tx" or "rx" depending on mboxes entries. + +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details +about the generic mailbox controller and client driver bindings. + +The mailbox is the only permitted method of calling the SCMI firmware. +Mailbox doorbell is used as a mechanism to alert the presence of a +messages and/or notification. + +Each protocol supported shall have a sub-node with corresponding compatible +as described in the following sections. If the platform supports dedicated +communication channel for a particular protocol, the 3 properties namely: +mboxes, mbox-names and shmem shall be present in the sub-node corresponding +to that protocol. + +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol + + +This binding uses the common clock binding[1]. + +Required properties: +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands. + +Power domain bindings for the power domains based on SCMI Message Protocol + + +This binding for the SCMI power domain providers uses the generic power +domain binding[2]. + +Required properties: + - #power-domain-cells : Should be 1. Contains the device or the power +domain ID value used by SCMI commands. + +Sensor bindings for the sensors based on SCMI Message Protocol +-- +SCMI provides an API to access the various sensors on the SoC. + +Required properties: +- #thermal-sensor-cells: should be set to 1. This property follows the +thermal device tree bindings[3]. + +Valid cell values are raw identifiers (Sensor ID) +as used by the firmware. Refer to platform details +for your implementation for the IDs to use. + +Reset signal bindings for the reset domains based on SCMI Message Protocol + + +This binding for the SCMI reset domain providers uses the generic reset +signal binding[5]. + +Required properties: + - #reset-cells : Should be 1. Contains the reset domain ID value used + by SCMI commands. + +SRAM and Shared Memory for SCMI +--- + +A small area of SRAM is reserved for SCMI communication between application +processors and SCP. + +The properties should follow the generic mmio-sram description found in [4] + +Each sub-node represents the reserved area for SC
[PATCH v3 8/8] firmware: smci: sandbox test for SCMI reset controllers
Add tests for SCMI reset controllers. A test device driver sandbox-scmi_devices.c is used to get reset resources, allowing further resets manipulation. Change sandbox-smci_agent to emulate 1 reset controller exposed through an agent. Add DM test scmi_resets to test this reset controller. Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: - New commit in the series, addresses review comments on test support. ut_dm_scmi_resets() tests SCMI resources are found and behave as expected for the implemented reset uclass methods. --- arch/sandbox/dts/test.dts| 6 + arch/sandbox/include/asm/scmi_test.h | 17 +++ configs/sandbox_defconfig| 1 + drivers/firmware/scmi/sandbox-scmi_agent.c | 117 ++- drivers/firmware/scmi/sandbox-scmi_devices.c | 30 - test/dm/scmi.c | 35 ++ 6 files changed, 200 insertions(+), 6 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 61acd8d79f..7023f33a67 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -366,6 +366,11 @@ reg = <0x14>; #clock-cells = <1>; }; + + reset_scmi0: protocol@16 { + reg = <0x16>; + #reset-cells = <1>; + }; }; sandbox-scmi-agent@1 { @@ -1065,6 +1070,7 @@ sandbox_scmi { compatible = "sandbox,scmi-devices"; clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; + resets = <&reset_scmi0 3>; }; pinctrl { diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index 4e09957bc7..de3b2bbcc2 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -22,16 +22,29 @@ struct sandbox_scmi_clk { ulong rate; }; +/** + * struct sandbox_scmi_reset - Simulated reset controller exposed by SCMI + * @asserted: Reset control state: true if asserted, false if desasserted + */ +struct sandbox_scmi_reset { + uint id; + bool asserted; +}; + /** * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent * @idx: Identifier for the SCMI agent, its index * @clk: Simulated clocks * @clk_count: Simulated clocks array size + * @clk: Simulated reset domains + * @clk_count: Simulated reset domains array size */ struct sandbox_scmi_agent { uint idx; struct sandbox_scmi_clk *clk; size_t clk_count; + struct sandbox_scmi_reset *reset; + size_t reset_count; }; /** @@ -48,10 +61,14 @@ struct sandbox_scmi_service { * struct sandbox_scmi_devices - Reference to devices probed through SCMI * @clk: Array the clock devices * @clk_count: Number of clock devices probed + * @reset: Array the reset controller devices + * @reset_count: Number of reset controller devices probed */ struct sandbox_scmi_devices { struct clk *clk; size_t clk_count; + struct reset_ctl *reset; + size_t reset_count; }; #ifdef CONFIG_SCMI_FIRMWARE diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 7d71c805dc..a2ebb3c971 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -220,6 +220,7 @@ CONFIG_REMOTEPROC_SANDBOX=y CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_RESET_SYSCON=y +CONFIG_RESET_SCMI=y CONFIG_DM_RNG=y CONFIG_DM_RTC=y CONFIG_RTC_RV8803=y diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 262efbd12c..01843a9827 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -18,19 +18,20 @@ * processing. It simulates few of the SCMI services for some of the * SCMI protocols embedded in U-Boot. Currently: * - SCMI clock protocol: emulate 2 agents each exposing few clocks + * - SCMI reset protocol: emulate 1 agents each exposing a reset * - * Agent #0 simulates 2 clocks. - * See IDs in scmi0_clk[] and "sandbox-scmi-agent@0" in test.dts. + * Agent #0 simulates 2 clocks and 1 reset domain. + * See IDs in scmi0_clk[]/scmi0_reset[] and "sandbox-scmi-agent@0" in test.dts. * * Agent #1 simulates 1 clock. * See IDs in scmi1_clk[] and "sandbox-scmi-agent@1" in test.dts. * - * All clocks are default disabled. + * All clocks are default disabled and reset levels down. * * This Driver exports sandbox_scmi_service_ct() for the test sequence to * get the state of the simulated services (clock state, rate, ...) and * check back-end device state reflects the request send through the - * various uclas
[PATCH v3 3/8] firmware: scmi: support Arm SMCCC transport
This change implements a SMCCC transport for SCMI exchanges. This implementation follows the Linux kernel as references implementation for SCMI message processing, using the SMT format for communication channel meta-data. Use of SMCCC transport in SCMI FDT bindings are defined in the Linux kernel DT bindings since v5.8. SMCCC with SMT is implemented in OP-TEE from tag 3.9.0 [2]. Links: [2] https://github.com/OP-TEE/optee_os/commit/a58c4d706d23 Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: - This is a followup of the SCMI agent patches posted in https://patchwork.ozlabs.org/project/uboot/list/?series=196253 The v3 splits commits and introduces a new uclass as requested. - This patch implements the same Arm SMCCC SCMI agent as presented in v2 but in its own source file smccc_agent.c, and based in smt.h. --- drivers/firmware/scmi/Kconfig | 4 +- drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/smccc_agent.c | 95 + 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 drivers/firmware/scmi/smccc_agent.c diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index c501bf4943..335d09c821 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -15,5 +15,5 @@ config SCMI_FIRMWARE Communications between agent (client) and the SCMI server are based on message exchange. Messages can be exchange over tranport - channels as a mailbox device with some piece of identified shared - memory. + channels as a mailbox device or an Arm SMCCC service with some + piece of identified shared memory. diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index d22f53efe7..2f782bbd55 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -1,4 +1,5 @@ obj-y += scmi_agent-uclass.o obj-y += smt.o +obj-$(CONFIG_ARM_SMCCC)+= smccc_agent.o obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o diff --git a/drivers/firmware/scmi/smccc_agent.c b/drivers/firmware/scmi/smccc_agent.c new file mode 100644 index 00..90707710e2 --- /dev/null +++ b/drivers/firmware/scmi/smccc_agent.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "smt.h" + +#define SMCCC_RET_NOT_SUPPORTED ((unsigned long)-1) + +/** + * struct scmi_smccc_channel - Description of an SCMI SMCCC transport + * @func_id: SMCCC function ID used by the SCMI transport + * @smt: Shared memory buffer + */ +struct scmi_smccc_channel { + ulong func_id; + struct scmi_smt smt; +}; + +static struct scmi_smccc_channel *scmi_smccc_get_priv(struct udevice *dev) +{ + return (struct scmi_smccc_channel *)dev_get_priv(dev); +} + +static int scmi_smccc_process_msg(struct udevice *dev, struct scmi_msg *msg) +{ + struct scmi_smccc_channel *chan = scmi_smccc_get_priv(dev); + struct arm_smccc_res res; + int ret; + + ret = scmi_write_msg_to_smt(dev, &chan->smt, msg); + if (ret) + return ret; + + arm_smccc_smc(chan->func_id, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 == SMCCC_RET_NOT_SUPPORTED) + ret = -ENXIO; + else + ret = scmi_read_resp_from_smt(dev, &chan->smt, msg); + + scmi_clear_smt_channel(&chan->smt); + + return ret; +} + +static int scmi_smccc_probe(struct udevice *dev) +{ + struct scmi_smccc_channel *chan = scmi_smccc_get_priv(dev); + u32 func_id; + int ret; + + if (dev_read_u32(dev, "arm,smc-id", &func_id)) { + dev_err(dev, "Missing property func-id\n"); + return -EINVAL; + } + + chan->func_id = func_id; + + ret = scmi_dt_get_smt_buffer(dev, &chan->smt); + if (ret) { + dev_err(dev, "Failed to get smt resources: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct udevice_id scmi_smccc_ids[] = { + { .compatible = "arm,scmi-smc" }, + { } +}; + +static const struct scmi_agent_ops scmi_smccc_ops = { + .process_msg = scmi_smccc_process_msg, +}; + +U_BOOT_DRIVER(scmi_smccc) = { + .name = "scmi-over-smccc", + .id = UCLASS_SCMI_AGENT, + .of_match = scmi_smccc_ids, + .priv_auto_alloc_size = sizeof(struct scmi_smccc_channel), + .probe = scmi_smccc_probe, + .ops= &scmi_smccc_ops, +}; -- 2.17.1
[PATCH v3 6/8] firmware: scmi: sandbox test for SCMI clocks
Add tests for SCMI clocks. A test device driver sandbox-scmi_devices.c is used to get clock resources, allowing further clock manipulation. Change sandbox-smci_agent to emulate 3 clocks exposed through 2 agents. Add DM test scmi_clocks to test these 3 clocks. Update DM test sandbox_scmi_agent with load/remove test sequences factorized by {load|remove}_sandbox_scmi_test_devices() helper functions. Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: - New commit in the series, addresses review comments on test support. ut_dm_scmi_clocks test SCMI are found and behave as expected for the implemented clk uclass methods. --- arch/sandbox/dts/test.dts| 15 ++ arch/sandbox/include/asm/scmi_test.h | 37 configs/sandbox_defconfig| 1 + drivers/firmware/scmi/Makefile | 2 +- drivers/firmware/scmi/sandbox-scmi_agent.c | 169 ++- drivers/firmware/scmi/sandbox-scmi_devices.c | 86 ++ test/dm/scmi.c | 139 ++- 7 files changed, 438 insertions(+), 11 deletions(-) create mode 100644 drivers/firmware/scmi/sandbox-scmi_devices.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dd3b43885e..61acd8d79f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -361,6 +361,11 @@ compatible = "sandbox,scmi-agent"; #address-cells = <1>; #size-cells = <0>; + + clk_scmi0: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; }; sandbox-scmi-agent@1 { @@ -368,6 +373,11 @@ #address-cells = <1>; #size-cells = <0>; + clk_scmi1: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + protocol@10 { reg = <0x10>; }; @@ -1052,6 +1062,11 @@ compatible = "sandbox,virtio2"; }; + sandbox_scmi { + compatible = "sandbox,scmi-devices"; + clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; + }; + pinctrl { compatible = "sandbox,pinctrl"; diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index a811fe19c3..4e09957bc7 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -10,12 +10,28 @@ struct udevice; struct sandbox_scmi_agent; struct sandbox_scmi_service; +/** + * struct sandbox_scmi_clk - Simulated clock exposed by SCMI + * @id:Identifier of the clock used in the SCMI protocol + * @enabled: Clock state: true if enabled, false if disabled + * @rate: Clock rate in Hertz + */ +struct sandbox_scmi_clk { + uint id; + bool enabled; + ulong rate; +}; + /** * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent * @idx: Identifier for the SCMI agent, its index + * @clk: Simulated clocks + * @clk_count: Simulated clocks array size */ struct sandbox_scmi_agent { uint idx; + struct sandbox_scmi_clk *clk; + size_t clk_count; }; /** @@ -28,16 +44,37 @@ struct sandbox_scmi_service { size_t agent_count; }; +/** + * struct sandbox_scmi_devices - Reference to devices probed through SCMI + * @clk: Array the clock devices + * @clk_count: Number of clock devices probed + */ +struct sandbox_scmi_devices { + struct clk *clk; + size_t clk_count; +}; + #ifdef CONFIG_SCMI_FIRMWARE /** * sandbox_scmi_service_context - Get the simulated SCMI services context * @return:Reference to backend simulated resources state */ struct sandbox_scmi_service *sandbox_scmi_service_ctx(void); + +/** + * sandbox_scmi_devices_get_ref - Get references to devices accessed through SCMI + * @return:Reference to the devices probed by the SCMI test + */ +struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(void); #else static inline struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) { return NULL; } + +static inline struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(void) +{ + return NULL; +} #endif /* CONFIG_SCMI_FIRMWARE */ #endif /* __SANDBOX_SCMI_TEST_H */ diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 2c130c01f0..7d71c805dc 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -122,6 +122,7 @@ CONFIG_BUTTON=y CONFIG_BUTTON_GPIO=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=
[PATCH v3 7/8] reset: add reset controller driver for SCMI agents
This change introduces a reset controller driver for SCMI agent devices. When SCMI agent and SCMI reset domain drivers are enabled, SCMI agent binds a reset controller device for each SCMI reset domain protocol devices enabled in the FDT. SCMI reset driver is embedded upon CONFIG_RESET_SCMI=y. If enabled, CONFIG_SCMI_AGENT is also enabled. SCMI Reset Domain protocol is defined in the SCMI specification [1]. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: - Upgrade to rename into devm_scmi_process_msg() and scmi.h split into scmi_*.h. - Fix message ID used in scmi_reset_request(). Changes in v2: - Change reset request() method to at least check the reset domain exists by sending a SCMI RESET_DOMAIN_ATTRIBUTE message. - Add inline description for the several structures. - Patch v1 R-b tag not applied since the above changes in this v2. BACKPORTED FROM v2020.10-rc2 to V2020.04 --- drivers/firmware/scmi/scmi_agent-uclass.c | 3 + drivers/reset/Kconfig | 8 +++ drivers/reset/Makefile| 1 + drivers/reset/reset-scmi.c| 81 +++ include/scmi_protocols.h | 60 + 5 files changed, 153 insertions(+) create mode 100644 drivers/reset/reset-scmi.c diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index e1694eff3d..54f798318f 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -73,6 +73,9 @@ static int scmi_bind_protocols(struct udevice *dev) case SCMI_PROTOCOL_ID_CLOCK: drv = DM_GET_DRIVER(scmi_clock); break; + case SCMI_PROTOCOL_ID_RESET_DOMAIN: + drv = DM_GET_DRIVER(scmi_reset_domain); + break; default: dev_info(dev, "Ignore unsupported SCMI protocol %#x\n", protocol_id); diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 253902ff57..ee5be0bc2f 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -173,4 +173,12 @@ config RESET_RASPBERRYPI relevant. This driver provides a reset controller capable of interfacing with RPi4's co-processor and model these firmware initialization routines as reset lines. + +config RESET_SCMI + bool "Enable SCMI reset domain driver" + select SCMI_FIRMWARE + help + Enable this option if you want to support reset controller + devices exposed by a SCMI agent based on SCMI reset domain + protocol communication with a SCMI server. endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 3c7f066ae3..625ec7168e 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_SIFIVE) += reset-sifive.o obj-$(CONFIG_RESET_SYSCON) += reset-syscon.o obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o +obj-$(CONFIG_RESET_SCMI) += reset-scmi.o diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c new file mode 100644 index 00..1bff8075ee --- /dev/null +++ b/drivers/reset/reset-scmi.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-2020 Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include + +static int scmi_reset_set_level(struct reset_ctl *rst, bool assert_not_deassert) +{ + struct scmi_rd_reset_in in = { + .domain_id = rst->id, + .flags = assert_not_deassert ? SCMI_RD_RESET_FLAG_ASSERT : 0, + .reset_state = 0, + }; + struct scmi_rd_reset_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_RESET_DOMAIN, + SCMI_RESET_DOMAIN_RESET, + in, out); + int ret; + + ret = devm_scmi_process_msg(rst->dev->parent, &msg); + if (ret) + return ret; + + return scmi_to_linux_errno(out.status); +} + +static int scmi_reset_assert(struct reset_ctl *rst) +{ + return scmi_reset_set_level(rst, true); +} + +static int scmi_reset_deassert(struct reset_ctl *rst) +{ + return scmi_reset_set_level(rst, false); +} + +static int scmi_reset_request(struct reset_ctl *rst) +{ + struct scmi_rd_attr_in in = { + .domain_id = rst->id, + }; + struct scmi_rd_attr_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_RESET_DOMAIN, + SCMI_RESET_DOMAIN_ATTRIBUTES, + in, out); + int ret; + + /* +* We do
[PATCH v3 5/8] clk: add clock driver for SCMI agents
This change introduces a clock driver for SCMI agent devices. When SCMI agent and SCMI clock drivers are enabled, SCMI agent binds a clock device for each SCMI clock protocol devices enabled in the FDT. SCMI clock driver is embedded upon CONFIG_CLK_SCMI=y. If enabled, CONFIG_SCMI_AGENT is also enabled. SCMI Clock protocol is defined in the SCMI specification [1]. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Lukasz Majewski Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v3: Changes in v2: - CONFIG_CLK_SCMI depends on CONFIG_SCMI_FIRMWARE instead of selecting CONFIG_SCMI_FIRMWARE. - Add inline comment description for structures and moves them to source file top. Add/fixup some functions inline description comments. - Replace rc with ret as return value local variable label. - Fix scmi_clk_get_rate() return value to propagate error number. - Fix scmi_clk_set_rate() to request synchronous rate set operation: drop flag SCMI_CLK_RATE_ASYNC_NORESP in the SCMI message payload. - Fix scmi_clk_set_rate() return value to return clock effective rate on success. --- drivers/clk/Kconfig | 8 ++ drivers/clk/Makefile | 1 + drivers/clk/clk_scmi.c| 99 +++ drivers/firmware/scmi/scmi_agent-uclass.c | 3 + include/scmi_protocols.h | 78 ++ 5 files changed, 189 insertions(+) create mode 100644 drivers/clk/clk_scmi.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6003e140b5..4dfbad7986 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -159,6 +159,14 @@ config CLK_CDCE9XX Enable the clock synthesizer driver for CDCE913/925/937/949 series of chips. +config CLK_SCMI + bool "Enable SCMI clock driver" + depends on SCMI_FIRMWARE + help + Enable this option if you want to support clock devices exposed + by a SCMI agent based on SCMI clock protocol communication + with a SCMI server. + source "drivers/clk/analogbits/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/exynos/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index cda4b4b605..d1e295ac7c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ +obj-$(CONFIG_CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c new file mode 100644 index 00..93a4819501 --- /dev/null +++ b/drivers/clk/clk_scmi.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-2020 Linaro Limited + */ +#include +#include +#include +#include +#include +#include + +static int scmi_clk_gate(struct clk *clk, int enable) +{ + struct scmi_clk_state_in in = { + .clock_id = clk->id, + .attributes = enable, + }; + struct scmi_clk_state_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_CONFIG_SET, + in, out); + int ret; + + ret = devm_scmi_process_msg(clk->dev->parent, &msg); + if (ret) + return ret; + + return scmi_to_linux_errno(out.status); +} + +static int scmi_clk_enable(struct clk *clk) +{ + return scmi_clk_gate(clk, 1); +} + +static int scmi_clk_disable(struct clk *clk) +{ + return scmi_clk_gate(clk, 0); +} + +static ulong scmi_clk_get_rate(struct clk *clk) +{ + struct scmi_clk_rate_get_in in = { + .clock_id = clk->id, + }; + struct scmi_clk_rate_get_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_RATE_GET, + in, out); + int ret; + + ret = devm_scmi_process_msg(clk->dev->parent, &msg); + if (ret < 0) + return ret; + + ret = scmi_to_linux_errno(out.status); + if (ret < 0) + return ret; + + return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb); +} + +static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) +{ + struct scmi_clk_rate_set_in in = { + .clock_id = clk->id, + .flags = SCMI_CLK_RATE_ROUND_CLOSEST, + .rate_lsb = (u32)rate, + .rate_msb = (u32)((u64)rate >> 32), + }; + struct scmi_clk_rate_set_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, +
Re: [RFC PATCH 0/7]
On Fri, 4 Sep 2020 at 14:25, Ard Biesheuvel wrote: > > On Fri, 4 Sep 2020 at 13:51, Patrick Delaunay wrote: > > > > arm: cache: cp15: don't map reserved region with no-map property > > > > Hi, > > > > On STM32MP15x platform we can use OP-TEE, loaded in DDR in a region > > protected > > by a firewall. This region is reserved in device with "no-map" property. > > > > But sometime the platform boot failed in U-boot on a Cortex A7 access to > > this > > region (depending of the binary and the issue can change with compiler > > version or > > with code alignment), then the firewall raise a error, for example: > > > > E/TC:0 tzc_it_handler:19 TZC permission failure > > E/TC:0 dump_fail_filter:420 Permission violation on filter 0 > > E/TC:0 dump_fail_filter:425 Violation @0xde5c6bf0, non-secure privileged > > read, AXI ID 5c0 > > E/TC:0 Panic > > > > After investigation, the forbidden access is a speculative request > > performed by > > the Cortex A7 because all the DDR is mapped as MEMORY with CACHEABLE > > property. > > > > The issue is solved only when the region reserved by OP-TEE is no more > > mapped > > in U-Boot (mapped as DEVICE/NON-CACHEABLE wasn't enough) as it is already > > done > > in Linux kernel. > > > > The only speculative accesses to such regions permitted by the > architecture are instruction fetches, which is why setting the nx > attribute is required on v7 for device mappings. > > Does uboot currently honour this requirement? I think current U-Boot honours the speculative side by using a IO memory default mapping strategy. If the reserved memory is used by a driver with a specific mapping, u-boot cannot ensure the mapping won't conflict with default mapping. For example OP-TEE defines a portion of this memory as non-secure cached shared memory. With Arm, we cannot map an area both as cached memory and as IO memory (Device/StronglyOrdered). So here, using a not-mapped strategy for "no-map" property looks better. Regards, Etienne > > > > I think that can be a general issue for ARM architecture: the no-map tag in > > device should be respected by U-boot, so I propose a generic solution in > > arm/lib/cache-cp15.c:dram_bank_mmu_setup(). > > > > This RFC serie is composed by 7 patches > > - 1..4/7: preliminary steps to support flags in library in lmb > > (as it is done in memblock.c in Linux) > > - 5/7: unitary test on the added feature in lmb lib > > - 6/7: save the no-map flags in lmb when the device tree is parsed > > - 7/7: update the generic behavior for "no-map" region in > >arm/lib/cache-cp15.c::dram_bank_mmu_setup() > > > > I can change this last patch if it is required by other ARM architecture; > > it is a weak function so I can avoid to map the region with "no-map" > > property in device tree only for STM32MP architecture > > (in arch/arm/mach-stm32mp/cpu.c). > > > > See also [1] which handle same speculative access on armv8 for area > > with Executable attribute. > > > > [1] > > http://patchwork.ozlabs.org/project/uboot/patch/20200903000106.5016-1-marek.bykow...@gmail.com/ > > > > Regards > > Patrick > > > > > > Patrick Delaunay (7): > > lmb: Add support of flags for no-map properties > > lmb: add lmb_is_reserved_flags > > lmb: remove lmb_region.size > > lmb: add lmb_dump_region() function > > test: lmb: add test for lmb_reserve_flags > > image-fdt: save no-map parameter of reserve-memory > > arm: cache: cp15: don't map the reserved region with no-map property > > > > arch/arm/include/asm/system.h | 3 + > > arch/arm/lib/cache-cp15.c | 17 +- > > common/image-fdt.c| 23 +--- > > include/lmb.h | 22 +++- > > lib/lmb.c | 100 +++--- > > test/lib/lmb.c| 89 ++ > > 6 files changed, 210 insertions(+), 44 deletions(-) > > > > -- > > 2.17.1 > >
Re: [PATCH v3 2/8] firmware: scmi: mailbox/smt agent device
On Tue, 8 Sep 2020 at 17:21, Simon Glass wrote: > > Hi Etienne, > > On Mon, 7 Sep 2020 at 08:50, Etienne Carriere > wrote: > > > > This change implements a mailbox transport using SMT format for SCMI > > exchanges. This implementation follows the Linux kernel and > > SCP-firmware [1] as references implementation for SCMI message > > processing using SMT format for communication channel meta-data. > > > > Use of mailboxes in SCMI FDT bindings are defined in the Linux kernel > > DT bindings since v4.17. > > > > Links: [1] https://github.com/ARM-software/SCP-firmware > > Signed-off-by: Etienne Carriere > > Cc: Simon Glass > > Cc: Peng Fan > > Cc: Sudeep Holla > > --- > > > > Changes in v3: > > - This is a followup of the SCMI agent patches posted in > > https://patchwork.ozlabs.org/project/uboot/list/?series=196253 > > The v3 splits commits and introduces a new uclass as requested. > > - This patch implements the same mailbox SCMI agent proposed in v2 > > but split over few source files. > > --- > > drivers/firmware/scmi/Kconfig | 6 +- > > drivers/firmware/scmi/Makefile| 2 + > > drivers/firmware/scmi/mailbox_agent.c | 107 > > drivers/firmware/scmi/smt.c | 139 ++ > > drivers/firmware/scmi/smt.h | 86 > > 5 files changed, 338 insertions(+), 2 deletions(-) > > create mode 100644 drivers/firmware/scmi/mailbox_agent.c > > create mode 100644 drivers/firmware/scmi/smt.c > > create mode 100644 drivers/firmware/scmi/smt.h > > Reviewed-by: Simon Glass Thanks for the reviews. > > diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c > > new file mode 100644 > > index 00..afe95a4736 > > --- /dev/null > > +++ b/drivers/firmware/scmi/smt.c > > @@ -0,0 +1,139 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights > > reserved. > > + * Copyright (C) 2019-2020 Linaro Limited. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "smt.h" > > + > > +/** > > + * Get shared memory configuration defined by the referred DT phandle > > + * Return with a errno compliant value. > > + */ > > +int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt) > > +{ > > + int ret; > > + struct ofnode_phandle_args args; > > + struct resource resource; > > + fdt32_t faddr; > > + phys_addr_t paddr; > > + > > + ret = dev_read_phandle_with_args(dev, "shmem", NULL, 0, 0, &args); > > + if (ret) > > + return ret; > > + > > + ret = ofnode_read_resource(args.node, 0, &resource); > > + if (ret) > > + return ret; > > + > > + faddr = cpu_to_fdt32(resource.start); > > + paddr = ofnode_translate_address(args.node, &faddr); > > + > > + smt->size = resource_size(&resource); > > + if (smt->size < sizeof(struct scmi_smt_header)) { > > + dev_err(dev, "Shared memory buffer too small\n"); > > + return -EINVAL; > > + } > > + > > + smt->buf = devm_ioremap(dev, paddr, smt->size); > > + if (!smt->buf) > > + return -ENOMEM; > > + > > +#ifdef __arm__ > > Should that be CONFIG_ARM ? Would covers CONFIG_ARM and CONFIG_ARM64, so OK. I'll send a patch v4. etienne > > > + if (dcache_status()) > > + mmu_set_region_dcache_behaviour((uintptr_t)smt->buf, > > + smt->size, DCACHE_OFF); > > +#endif > > + > > + return 0; > > +} > > + > [..] > > Regards, > Simon
Re: [PATCH v3 3/8] firmware: scmi: support Arm SMCCC transport
On Tue, 8 Sep 2020 at 17:21, Simon Glass wrote: > > Hi Etienne, > > On Mon, 7 Sep 2020 at 08:50, Etienne Carriere > wrote: > > > > This change implements a SMCCC transport for SCMI exchanges. This > > implementation follows the Linux kernel as references implementation > > for SCMI message processing, using the SMT format for communication > > channel meta-data. > > > > Use of SMCCC transport in SCMI FDT bindings are defined in the Linux > > kernel DT bindings since v5.8. SMCCC with SMT is implemented in OP-TEE > > from tag 3.9.0 [2]. > > > > Links: [2] https://github.com/OP-TEE/optee_os/commit/a58c4d706d23 > > Signed-off-by: Etienne Carriere > > Cc: Simon Glass > > Cc: Peng Fan > > Cc: Sudeep Holla > > --- > > > > Changes in v3: > > - This is a followup of the SCMI agent patches posted in > > https://patchwork.ozlabs.org/project/uboot/list/?series=196253 > > The v3 splits commits and introduces a new uclass as requested. > > - This patch implements the same Arm SMCCC SCMI agent as presented > > in v2 but in its own source file smccc_agent.c, and based in smt.h. > > --- > > drivers/firmware/scmi/Kconfig | 4 +- > > drivers/firmware/scmi/Makefile | 1 + > > drivers/firmware/scmi/smccc_agent.c | 95 + > > 3 files changed, 98 insertions(+), 2 deletions(-) > > create mode 100644 drivers/firmware/scmi/smccc_agent.c > > > > Reviewed-by: Simon Glass > > nits below > > > diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig > > index c501bf4943..335d09c821 100644 > > --- a/drivers/firmware/scmi/Kconfig > > +++ b/drivers/firmware/scmi/Kconfig > > @@ -15,5 +15,5 @@ config SCMI_FIRMWARE > > > > Communications between agent (client) and the SCMI server are > > based on message exchange. Messages can be exchange over tranport > > - channels as a mailbox device with some piece of identified shared > > - memory. > > + channels as a mailbox device or an Arm SMCCC service with some > > + piece of identified shared memory. > > diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile > > index d22f53efe7..2f782bbd55 100644 > > --- a/drivers/firmware/scmi/Makefile > > +++ b/drivers/firmware/scmi/Makefile > > @@ -1,4 +1,5 @@ > > obj-y += scmi_agent-uclass.o > > obj-y += smt.o > > +obj-$(CONFIG_ARM_SMCCC)+= smccc_agent.o > > obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o > > obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o > > diff --git a/drivers/firmware/scmi/smccc_agent.c > > b/drivers/firmware/scmi/smccc_agent.c > > new file mode 100644 > > index 00..90707710e2 > > --- /dev/null > > +++ b/drivers/firmware/scmi/smccc_agent.c > > @@ -0,0 +1,95 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (C) 2020 Linaro Limited. > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > That should go below the next one. acked. > > + > > +#include > > +#include > > + > > +#include "smt.h" > > + > > +#define SMCCC_RET_NOT_SUPPORTED ((unsigned long)-1) > > + > > +/** > > + * struct scmi_smccc_channel - Description of an SCMI SMCCC transport > > + * @func_id: SMCCC function ID used by the SCMI transport > > + * @smt: Shared memory buffer > > + */ > > +struct scmi_smccc_channel { > > + ulong func_id; > > + struct scmi_smt smt; > > +}; > > + > > +static struct scmi_smccc_channel *scmi_smccc_get_priv(struct udevice *dev) > > +{ > > + return (struct scmi_smccc_channel *)dev_get_priv(dev); > > You shouldn't need that cast acked. So no need for helper scmi_smccc_get_priv(), caller can call dev_get_priv() straight. etienne > > [..] > > Regards, > Simon
Re: [PATCH v3 6/8] firmware: scmi: sandbox test for SCMI clocks
On Tue, 8 Sep 2020 at 17:21, Simon Glass wrote: > > Hi Etienne, > > On Mon, 7 Sep 2020 at 08:50, Etienne Carriere > wrote: > > > > Add tests for SCMI clocks. A test device driver sandbox-scmi_devices.c > > is used to get clock resources, allowing further clock manipulation. > > > > Change sandbox-smci_agent to emulate 3 clocks exposed through 2 agents. > > Add DM test scmi_clocks to test these 3 clocks. > > Update DM test sandbox_scmi_agent with load/remove test sequences > > factorized by {load|remove}_sandbox_scmi_test_devices() helper functions. > > > > Signed-off-by: Etienne Carriere > > Cc: Simon Glass > > Cc: Peng Fan > > Cc: Sudeep Holla > > --- > > > > Changes in v3: > > - New commit in the series, addresses review comments on test support. > > ut_dm_scmi_clocks test SCMI are found and behave as expected for the > > implemented clk uclass methods. > > --- > > arch/sandbox/dts/test.dts| 15 ++ > > arch/sandbox/include/asm/scmi_test.h | 37 > > configs/sandbox_defconfig| 1 + > > drivers/firmware/scmi/Makefile | 2 +- > > drivers/firmware/scmi/sandbox-scmi_agent.c | 169 ++- > > drivers/firmware/scmi/sandbox-scmi_devices.c | 86 ++ > > test/dm/scmi.c | 139 ++- > > 7 files changed, 438 insertions(+), 11 deletions(-) > > create mode 100644 drivers/firmware/scmi/sandbox-scmi_devices.c > > Reviewed-by: Simon Glass > > Nits below > > [..] > > > diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c > > b/drivers/firmware/scmi/sandbox-scmi_devices.c > > new file mode 100644 > > index 00..2ce8e664df > > --- /dev/null > > +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c > > @@ -0,0 +1,86 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (C) 2020, Linaro Limited > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +/* > > + * Simulate to some extend a SCMI exhange. > > extend, exchange acked. > > > + * This drivers gets SCMI resources and offers API function to the > > + * SCMI test sequence manipulate the resources. > > + */ > > + > > +#define SCMI_TEST_DEVICES_CLK_COUNT3 > > + > > +/* > > + * These tables store de handles used in the various uclasses device > > function > > s/de/the/ ? acked. > > > + * that are instancied when probed through the SCMI agent. Use a static > > spelling acked, thanks. > > > + * memory allocation to ease sharing with test sequence implementation. > > + */ > > +static struct clk sandbox_scmi_clk_device[SCMI_TEST_DEVICES_CLK_COUNT]; > > +static struct sandbox_scmi_devices sandbox_scmi_devhld; > > This should really be in a struct, I think, pointed to by > dev_get_priv() on this device. I do try to avoid BSS with driver > model, although it is not a hard rule with test code. I used a static structure here to ease sharing context reference with the test sequence implementation. Context reference returned by sandbox_scmi_devices_ctx() is always reliable for the sequence. (not possibly dereference in which case the test may segfault). I can go this way if you prefer no BSS in drivers (Note this is a sandbox driver). I'll update the test accordingly. etienne > > > + > > +struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(void) > > +{ > > + return &sandbox_scmi_devhld; > > +} > > + > > +static void dereference_device_handles(struct sandbox_scmi_devices > > *devices) > > +{ > > + devices->clk = NULL; > > + devices->clk_count = 0; > > +} > > + > > +static int sandbox_scmi_devices_remove(struct udevice *dev) > > +{ > > + struct sandbox_scmi_devices *devices = sandbox_scmi_devices_ctx(); > > + > > + dereference_device_handles(devices); > > + > > + return 0; > > +} > > + > > +static int sandbox_scmi_devices_probe(struct udevice *dev) > > +{ > > + struct sandbox_scmi_devices *devices = sandbox_scmi_devices_ctx(); > > + int rc; > > + size_t n; > > + > > + devices->clk = sandbox_scmi_clk_device; > > + devices->clk_count = SCMI_TEST_DEVICES_CLK_COUNT; > > + > > + for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { > > + rc = clk_get
Re: [PATCH v3 6/8] firmware: scmi: sandbox test for SCMI clocks
On Wed, 9 Sep 2020 at 16:35, Simon Glass wrote: > > Hi Etienne, > > On Wed, 9 Sep 2020 at 03:58, Etienne Carriere > wrote: > > > > On Tue, 8 Sep 2020 at 17:21, Simon Glass wrote: > > > > > > Hi Etienne, > > > > > > On Mon, 7 Sep 2020 at 08:50, Etienne Carriere > > > wrote: > > > > > > > > Add tests for SCMI clocks. A test device driver sandbox-scmi_devices.c > > > > is used to get clock resources, allowing further clock manipulation. > > > > > > > > Change sandbox-smci_agent to emulate 3 clocks exposed through 2 agents. > > > > Add DM test scmi_clocks to test these 3 clocks. > > > > Update DM test sandbox_scmi_agent with load/remove test sequences > > > > factorized by {load|remove}_sandbox_scmi_test_devices() helper > > > > functions. > > > > > > > > Signed-off-by: Etienne Carriere > > > > Cc: Simon Glass > > > > Cc: Peng Fan > > > > Cc: Sudeep Holla > > > > --- > > > > > > > > Changes in v3: > > > > - New commit in the series, addresses review comments on test support. > > > > ut_dm_scmi_clocks test SCMI are found and behave as expected for the > > > > implemented clk uclass methods. > > > > --- > > > > arch/sandbox/dts/test.dts| 15 ++ > > > > arch/sandbox/include/asm/scmi_test.h | 37 > > > > configs/sandbox_defconfig| 1 + > > > > drivers/firmware/scmi/Makefile | 2 +- > > > > drivers/firmware/scmi/sandbox-scmi_agent.c | 169 ++- > > > > drivers/firmware/scmi/sandbox-scmi_devices.c | 86 ++ > > > > test/dm/scmi.c | 139 ++- > > > > 7 files changed, 438 insertions(+), 11 deletions(-) > > > > create mode 100644 drivers/firmware/scmi/sandbox-scmi_devices.c > > > > > > Reviewed-by: Simon Glass > > > > > > Nits below > > > > > > [..] > > > > > + * memory allocation to ease sharing with test sequence implementation. > > > > + */ > > > > +static struct clk sandbox_scmi_clk_device[SCMI_TEST_DEVICES_CLK_COUNT]; > > > > +static struct sandbox_scmi_devices sandbox_scmi_devhld; > > > > > > This should really be in a struct, I think, pointed to by > > > dev_get_priv() on this device. I do try to avoid BSS with driver > > > model, although it is not a hard rule with test code. > > > > I used a static structure here to ease sharing context reference with > > the test sequence implementation. > > Is that in a different file? I made the helper function sandbox_scmi_devices_ctx() exported by sandbox-scmi_devices.c that references probed devices. The function is called from test/dm/scmi.c to run the test (actions & verifications). > > > Context reference returned by sandbox_scmi_devices_ctx() is always > > reliable for the sequence. > > (not possibly dereference in which case the test may segfault). > > > > I can go this way if you prefer no BSS in drivers (Note this is a > > sandbox driver). I'll update the test accordingly. > > If you have a reason to use BSS for a sandbox driver that is OK. I > don't quite understand the problem you are solving though. If private > data is allocated too late, you can allocate the info as platdata > which happens when the device is bound, and then use > dev_get_platdata(). > > But ultimately it is up to you, as this is a test driver. It just > helps to avoid people copying a pattern to their own driver. Ok. I'll try to keep it simple. Regards, etienne > > [..] > > Regards, > Simon
[PATCH v4 1/8] firmware: add SCMI agent uclass
This change introduces SCMI agent uclass to interact with a firmware using the SCMI protocols [1]. SCMI agent uclass currently supports a single method to request processing of the SCMI message by an identified server. A SCMI message is made of a byte payload associated to a protocol ID and a message ID, all defined by the SCMI specification [1]. On return from process_msg() method, the caller gets the service response. SCMI agent uclass defines a post bind generic sequence for all devices. The sequence binds all the SCMI protocols listed in the FDT for that SCMI agent device. Currently none, but later change will introduce protocols. This change implements a simple sandbox device for the SCMI agent uclass. The sandbox nicely answers SCMI_NOT_SUPPORTED to SCMI messages. To prepare for further test support, the sandbox exposes a architecture function for test application to read the sandbox emulated devices state. Currently supports 2 SCMI agents, identified by an ID in the FDT device name. The simplistic DM test does nothing yet. SCMI agent uclass is designed for platforms that embed a SCMI server in a firmware hosted somewhere, for example in a companion co-processor or in the secure world of the executing processor. SCMI protocols allow an SCMI agent to discover and access external resources as clock, reset controllers and more. SCMI agent and server communicate following the SCMI specification [1]. This SCMI agent implementation complies with the DT bindings defined in the Linux kernel source tree regarding SCMI agent description since v5.8. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla Reviewed-by: Simon Glass --- Changes in v4: - Remove local helper function dev2agent() used to hide a useless cast. Changes in v3: - Address comments about adding a new uclass and some sandbox test from v2 in https://patchwork.ozlabs.org/project/uboot/list/?series=196253 - New directory drivers/firmware/scmi/. The path mimics Linux kernel source tree for the equivalent driver. - Split scmi.h (patch v2) into scmi_protocols.h, scmi_agent.h and scmi_agent-uclass.h. - Create new uclass UCLASS_SCMI_AGENT. - Introduce a simple sandbox on that agent. Mailbox and smccc agents are moved to specific commits in the series. Changes in v2: - Fix CONFIG_SCMI_FIRMWARE description with explicit SCMI reference. - Move struct, enum and macro definitions at source file top and add inline comment description for the structures and local functions. - Replace rc with ret as return value local variable label. - Use explicit return 0 on successful return paths. - Replace EINVAL with more accurate error numbers. - Use dev_read_u32() instead of ofnode_read_u32(dev_ofnode(), ...). - Use memcpy_toio()/memcpy_fromio() when copying message payload to/from IO memory. - Embed mailbox transport resources upon CONFIG_DM_MAILBOX and SMCCC transport resources upon CONFIG_ARM_SMCCC. Note: review comments on defining a uclass and sandbox for SCMI transport drivers are NOT addressed in this v2. Main issue is that there is no driver/device defined for SCMI transport layer as well as and no defined compatible ID in the SCMI DT bindings documentation. --- arch/sandbox/dts/test.dts | 16 +++ arch/sandbox/include/asm/scmi_test.h | 43 +++ configs/sandbox_defconfig | 2 + drivers/firmware/Kconfig | 2 + drivers/firmware/Makefile | 1 + drivers/firmware/scmi/Kconfig | 17 +++ drivers/firmware/scmi/Makefile | 2 + drivers/firmware/scmi/sandbox-scmi_agent.c | 142 + drivers/firmware/scmi/scmi_agent-uclass.c | 107 include/dm/uclass-id.h | 1 + include/scmi_agent-uclass.h| 24 include/scmi_agent.h | 68 ++ include/scmi_protocols.h | 41 ++ test/dm/Makefile | 1 + test/dm/scmi.c | 38 ++ 15 files changed, 505 insertions(+) create mode 100644 arch/sandbox/include/asm/scmi_test.h create mode 100644 drivers/firmware/scmi/Kconfig create mode 100644 drivers/firmware/scmi/Makefile create mode 100644 drivers/firmware/scmi/sandbox-scmi_agent.c create mode 100644 drivers/firmware/scmi/scmi_agent-uclass.c create mode 100644 include/scmi_agent-uclass.h create mode 100644 include/scmi_agent.h create mode 100644 include/scmi_protocols.h create mode 100644 test/dm/scmi.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 9f45c48e4e..dd3b43885e 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -356,6 +356,22 @@ sandbox_firmware: sandbox-firmware { compatible = "sandbox,firmware"; }; + + sa
[PATCH v4 2/8] firmware: scmi: mailbox/smt agent device
This change implements a mailbox transport using SMT format for SCMI exchanges. This implementation follows the Linux kernel and SCP-firmware [1] as references implementation for SCMI message processing using SMT format for communication channel meta-data. Use of mailboxes in SCMI FDT bindings are defined in the Linux kernel DT bindings since v4.17. Links: [1] https://github.com/ARM-software/SCP-firmware Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v4: - Replace __arm__ with CONFIG_ARM. - Remove cast for priv reference hence remove helper scmi_mbox_get_priv(). Changes in v3: - This is a followup of the SCMI agent patches posted in https://patchwork.ozlabs.org/project/uboot/list/?series=196253 The v3 splits commits and introduces a new uclass as requested. - This patch implements the same mailbox SCMI agent proposed in v2 but split over few source files. --- drivers/firmware/scmi/Kconfig | 6 +- drivers/firmware/scmi/Makefile| 2 + drivers/firmware/scmi/mailbox_agent.c | 102 +++ drivers/firmware/scmi/smt.c | 139 ++ drivers/firmware/scmi/smt.h | 86 5 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 drivers/firmware/scmi/mailbox_agent.c create mode 100644 drivers/firmware/scmi/smt.c create mode 100644 drivers/firmware/scmi/smt.h diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index 57e2ebbe42..c501bf4943 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -2,7 +2,7 @@ config SCMI_FIRMWARE bool "Enable SCMI support" select FIRMWARE select OF_TRANSLATE - depends on SANDBOX + depends on SANDBOX || DM_MAILBOX help System Control and Management Interface (SCMI) is a communication protocol that defines standard interfaces for power, performance @@ -14,4 +14,6 @@ config SCMI_FIRMWARE or a companion host in the CPU system. Communications between agent (client) and the SCMI server are - based on message exchange. + based on message exchange. Messages can be exchange over tranport + channels as a mailbox device with some piece of identified shared + memory. diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index 336ea1f2a3..d22f53efe7 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -1,2 +1,4 @@ obj-y += scmi_agent-uclass.o +obj-y += smt.o +obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o diff --git a/drivers/firmware/scmi/mailbox_agent.c b/drivers/firmware/scmi/mailbox_agent.c new file mode 100644 index 00..7d9fb3622e --- /dev/null +++ b/drivers/firmware/scmi/mailbox_agent.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smt.h" + +#define TIMEOUT_US_10MS1 + +/** + * struct scmi_mbox_channel - Description of an SCMI mailbox transport + * @smt: Shared memory buffer + * @mbox: Mailbox channel description + * @timeout_us:Timeout in microseconds for the mailbox transfer + */ +struct scmi_mbox_channel { + struct scmi_smt smt; + struct mbox_chan mbox; + ulong timeout_us; +}; + +static int scmi_mbox_process_msg(struct udevice *dev, struct scmi_msg *msg) +{ + struct scmi_mbox_channel *chan = dev_get_priv(dev); + int ret; + + ret = scmi_write_msg_to_smt(dev, &chan->smt, msg); + if (ret) + return ret; + + /* Give shm addr to mbox in case it is meaningful */ + ret = mbox_send(&chan->mbox, chan->smt.buf); + if (ret) { + dev_err(dev, "Message send failed: %d\n", ret); + goto out; + } + + /* Receive the response */ + ret = mbox_recv(&chan->mbox, chan->smt.buf, chan->timeout_us); + if (ret) { + dev_err(dev, "Response failed: %d, abort\n", ret); + goto out; + } + + ret = scmi_read_resp_from_smt(dev, &chan->smt, msg); + +out: + scmi_clear_smt_channel(&chan->smt); + + return ret; +} + +int scmi_mbox_probe(struct udevice *dev) +{ + struct scmi_mbox_channel *chan = dev_get_priv(dev); + int ret; + + chan->timeout_us = TIMEOUT_US_10MS; + + ret = mbox_get_by_index(dev, 0, &chan->mbox); + if (ret) { + dev_err(dev, "Failed to find mailbox: %d\n", ret); + goto out; + } + + ret = scmi_dt_get_smt_buffer(dev, &chan->smt); + if (ret) + dev_err(dev, "Failed to get shm resources: %
[PATCH v4 3/8] firmware: scmi: support Arm SMCCC transport
This change implements a SMCCC transport for SCMI exchanges. This implementation follows the Linux kernel as references implementation for SCMI message processing, using the SMT format for communication channel meta-data. Use of SMCCC transport in SCMI FDT bindings are defined in the Linux kernel DT bindings since v5.8. SMCCC with SMT is implemented in OP-TEE from tag 3.9.0 [2]. Links: [2] https://github.com/OP-TEE/optee_os/commit/a58c4d706d23 Signed-off-by: Etienne Carriere Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v4: - Update CONFIG_SCMI_FIRMWARE dependencies regarding CONFIG_ARM_SMCCC. - Remove useless cast hence remove helper dev2agent() to get dev private. - Fix header file inclusion ordering. Changes in v3: - This is a followup of the SCMI agent patches posted in https://patchwork.ozlabs.org/project/uboot/list/?series=196253 The v3 splits commits and introduces a new uclass as requested. - This patch implements the same Arm SMCCC SCMI agent as presented in v2 but in its own source file smccc_agent.c, and based in smt.h. --- drivers/firmware/scmi/Kconfig | 6 +- drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/smccc_agent.c | 89 + 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 drivers/firmware/scmi/smccc_agent.c diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index c501bf4943..c3a109beac 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -2,7 +2,7 @@ config SCMI_FIRMWARE bool "Enable SCMI support" select FIRMWARE select OF_TRANSLATE - depends on SANDBOX || DM_MAILBOX + depends on SANDBOX || DM_MAILBOX || ARM_SMCCC help System Control and Management Interface (SCMI) is a communication protocol that defines standard interfaces for power, performance @@ -15,5 +15,5 @@ config SCMI_FIRMWARE Communications between agent (client) and the SCMI server are based on message exchange. Messages can be exchange over tranport - channels as a mailbox device with some piece of identified shared - memory. + channels as a mailbox device or an Arm SMCCC service with some + piece of identified shared memory. diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index d22f53efe7..2f782bbd55 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -1,4 +1,5 @@ obj-y += scmi_agent-uclass.o obj-y += smt.o +obj-$(CONFIG_ARM_SMCCC)+= smccc_agent.o obj-$(CONFIG_DM_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o diff --git a/drivers/firmware/scmi/smccc_agent.c b/drivers/firmware/scmi/smccc_agent.c new file mode 100644 index 00..85dbf9195e --- /dev/null +++ b/drivers/firmware/scmi/smccc_agent.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smt.h" + +#define SMCCC_RET_NOT_SUPPORTED ((unsigned long)-1) + +/** + * struct scmi_smccc_channel - Description of an SCMI SMCCC transport + * @func_id: SMCCC function ID used by the SCMI transport + * @smt: Shared memory buffer + */ +struct scmi_smccc_channel { + ulong func_id; + struct scmi_smt smt; +}; + +static int scmi_smccc_process_msg(struct udevice *dev, struct scmi_msg *msg) +{ + struct scmi_smccc_channel *chan = dev_get_priv(dev); + struct arm_smccc_res res; + int ret; + + ret = scmi_write_msg_to_smt(dev, &chan->smt, msg); + if (ret) + return ret; + + arm_smccc_smc(chan->func_id, 0, 0, 0, 0, 0, 0, 0, &res); + if (res.a0 == SMCCC_RET_NOT_SUPPORTED) + ret = -ENXIO; + else + ret = scmi_read_resp_from_smt(dev, &chan->smt, msg); + + scmi_clear_smt_channel(&chan->smt); + + return ret; +} + +static int scmi_smccc_probe(struct udevice *dev) +{ + struct scmi_smccc_channel *chan = dev_get_priv(dev); + u32 func_id; + int ret; + + if (dev_read_u32(dev, "arm,smc-id", &func_id)) { + dev_err(dev, "Missing property func-id\n"); + return -EINVAL; + } + + chan->func_id = func_id; + + ret = scmi_dt_get_smt_buffer(dev, &chan->smt); + if (ret) { + dev_err(dev, "Failed to get smt resources: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct udevice_id scmi_smccc_ids[] = { + { .compatible = "arm,scmi-smc" }, + { } +}; + +static const struct scmi_agent_ops scmi_smccc_ops = { + .process_msg = scmi_smccc_process_msg, +}; + +U_BOOT_DRIVER(scmi_smccc) = { +
[PATCH v4 4/8] dt-bindings: arm: SCMI bindings documentation
Dump SCMI DT bindings documentation from Linux kernel source tree v5.8-rc1. Signed-off-by: Etienne Carriere Reviewed-by: Simon Glass --- No change in v4. No change in v3. Changes in v2: - No change but added R-b tag. - Yet a question: do we need to add this binding doc in U-Boot since already existing in Linux DT bindings docs? Related to review comment https://www.mail-archive.com/u-boot@lists.denx.de/msg377725.html --- doc/device-tree-bindings/arm/arm,scmi.txt | 197 ++ 1 file changed, 197 insertions(+) create mode 100644 doc/device-tree-bindings/arm/arm,scmi.txt diff --git a/doc/device-tree-bindings/arm/arm,scmi.txt b/doc/device-tree-bindings/arm/arm,scmi.txt new file mode 100644 index 00..1f293ea24c --- /dev/null +++ b/doc/device-tree-bindings/arm/arm,scmi.txt @@ -0,0 +1,197 @@ +System Control and Management Interface (SCMI) Message Protocol +-- + +The SCMI is intended to allow agents such as OSPM to manage various functions +that are provided by the hardware platform it is running on, including power +and performance functions. + +This binding is intended to define the interface the firmware implementing +the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control +and Management Interface Platform Design Document")[0] provide for OSPM in +the device tree. + +Required properties: + +The scmi node with the following properties shall be under the /firmware/ node. + +- compatible : shall be "arm,scmi" or "arm,scmi-smc" for smc/hvc transports +- mboxes: List of phandle and mailbox channel specifiers. It should contain + exactly one or two mailboxes, one for transmitting messages("tx") + and another optional for receiving the notifications("rx") if + supported. +- shmem : List of phandle pointing to the shared memory(SHM) area as per + generic mailbox client binding. +- #address-cells : should be '1' if the device has sub-nodes, maps to + protocol identifier for a given sub-node. +- #size-cells : should be '0' as 'reg' property doesn't have any size + associated with it. +- arm,smc-id : SMC id required when using smc or hvc transports + +Optional properties: + +- mbox-names: shall be "tx" or "rx" depending on mboxes entries. + +See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details +about the generic mailbox controller and client driver bindings. + +The mailbox is the only permitted method of calling the SCMI firmware. +Mailbox doorbell is used as a mechanism to alert the presence of a +messages and/or notification. + +Each protocol supported shall have a sub-node with corresponding compatible +as described in the following sections. If the platform supports dedicated +communication channel for a particular protocol, the 3 properties namely: +mboxes, mbox-names and shmem shall be present in the sub-node corresponding +to that protocol. + +Clock/Performance bindings for the clocks/OPPs based on SCMI Message Protocol + + +This binding uses the common clock binding[1]. + +Required properties: +- #clock-cells : Should be 1. Contains the Clock ID value used by SCMI commands. + +Power domain bindings for the power domains based on SCMI Message Protocol + + +This binding for the SCMI power domain providers uses the generic power +domain binding[2]. + +Required properties: + - #power-domain-cells : Should be 1. Contains the device or the power +domain ID value used by SCMI commands. + +Sensor bindings for the sensors based on SCMI Message Protocol +-- +SCMI provides an API to access the various sensors on the SoC. + +Required properties: +- #thermal-sensor-cells: should be set to 1. This property follows the +thermal device tree bindings[3]. + +Valid cell values are raw identifiers (Sensor ID) +as used by the firmware. Refer to platform details +for your implementation for the IDs to use. + +Reset signal bindings for the reset domains based on SCMI Message Protocol + + +This binding for the SCMI reset domain providers uses the generic reset +signal binding[5]. + +Required properties: + - #reset-cells : Should be 1. Contains the reset domain ID value used + by SCMI commands. + +SRAM and Shared Memory for SCMI +--- + +A small area of SRAM is reserved for SCMI communication between application +processors and SCP. + +The properties should follow the generic mmio-sram description found in [4] + +Each sub-node represents the reserv
[PATCH v4 5/8] clk: add clock driver for SCMI agents
This change introduces a clock driver for SCMI agent devices. When SCMI agent and SCMI clock drivers are enabled, SCMI agent binds a clock device for each SCMI clock protocol devices enabled in the FDT. SCMI clock driver is embedded upon CONFIG_CLK_SCMI=y. If enabled, CONFIG_SCMI_AGENT is also enabled. SCMI Clock protocol is defined in the SCMI specification [1]. Links: [1] https://developer.arm.com/architectures/system-architectures/software-standards/scmi Signed-off-by: Etienne Carriere Cc: Lukasz Majewski Cc: Simon Glass Cc: Peng Fan Cc: Sudeep Holla --- Changes in v4: - Condition DM_GET_DRIVER(scmi_clock) to IS_ENABLED(CONFIG_CLK_SCMI) to prevent a build error (linker) when CONFIG_CLK_SCMI is disabled. Changes in v3: - Rebased in the series without major conflict. Changes in v2: - CONFIG_CLK_SCMI depends on CONFIG_SCMI_FIRMWARE instead of selecting CONFIG_SCMI_FIRMWARE. - Add inline comment description for structures and moves them to source file top. Add/fixup some functions inline description comments. - Replace rc with ret as return value local variable label. - Fix scmi_clk_get_rate() return value to propagate error number. - Fix scmi_clk_set_rate() to request synchronous rate set operation: drop flag SCMI_CLK_RATE_ASYNC_NORESP in the SCMI message payload. - Fix scmi_clk_set_rate() return value to return clock effective rate on success. --- drivers/clk/Kconfig | 8 ++ drivers/clk/Makefile | 1 + drivers/clk/clk_scmi.c| 99 +++ drivers/firmware/scmi/scmi_agent-uclass.c | 14 +++- include/scmi_protocols.h | 78 ++ 5 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 drivers/clk/clk_scmi.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6003e140b5..4dfbad7986 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -159,6 +159,14 @@ config CLK_CDCE9XX Enable the clock synthesizer driver for CDCE913/925/937/949 series of chips. +config CLK_SCMI + bool "Enable SCMI clock driver" + depends on SCMI_FIRMWARE + help + Enable this option if you want to support clock devices exposed + by a SCMI agent based on SCMI clock protocol communication + with a SCMI server. + source "drivers/clk/analogbits/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/exynos/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index cda4b4b605..d1e295ac7c 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o obj-$(CONFIG_CLK_OWL) += owl/ obj-$(CONFIG_CLK_RENESAS) += renesas/ +obj-$(CONFIG_CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c new file mode 100644 index 00..93a4819501 --- /dev/null +++ b/drivers/clk/clk_scmi.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-2020 Linaro Limited + */ +#include +#include +#include +#include +#include +#include + +static int scmi_clk_gate(struct clk *clk, int enable) +{ + struct scmi_clk_state_in in = { + .clock_id = clk->id, + .attributes = enable, + }; + struct scmi_clk_state_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_CONFIG_SET, + in, out); + int ret; + + ret = devm_scmi_process_msg(clk->dev->parent, &msg); + if (ret) + return ret; + + return scmi_to_linux_errno(out.status); +} + +static int scmi_clk_enable(struct clk *clk) +{ + return scmi_clk_gate(clk, 1); +} + +static int scmi_clk_disable(struct clk *clk) +{ + return scmi_clk_gate(clk, 0); +} + +static ulong scmi_clk_get_rate(struct clk *clk) +{ + struct scmi_clk_rate_get_in in = { + .clock_id = clk->id, + }; + struct scmi_clk_rate_get_out out; + struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, + SCMI_CLOCK_RATE_GET, + in, out); + int ret; + + ret = devm_scmi_process_msg(clk->dev->parent, &msg); + if (ret < 0) + return ret; + + ret = scmi_to_linux_errno(out.status); + if (ret < 0) + return ret; + + return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb); +} + +static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) +{ + struct scmi_clk_rate_set_in in = { + .clock_id = clk->id, + .flags = SCMI_CLK_RATE_ROUND_CLOSEST, +