Re: [PATCH v2 00/21] FWU: Migrate FWU metadata to version 2

2024-02-20 Thread Etienne CARRIERE - foss
Hello Sughosh,

Sorry for this very late reply especially since I have a quite negative 
feedback  on the proposed changes.

I don't think FWU metadata version 1 should be removed from U-Boot support.
There are existing immutable boot agent relying on format v1, starting from the 
Synquacer boards based on SCP-firmware v2.11 [1] onward (at least up to latest 
v2.13 tag) and the stm32mp1 platforms based on TF-A v2.7 [2] onward (at least 
up to latest tag v2.10). These platforms should be able to update there EFI 
firmware hence needing the update agent (U-Boot) to support format v1.

With the proposed series, the new format v2 contains the same information the 
previous mdata v1 based implementation did (apart that some info where built-in 
whereas v2 describe them from the mdata storage area).
Could it be possible the implementation support both, using for example a 
internal structure fed from either format v1 or v2 content read from the 
storage, and used to update the mdata  v1 or v2 format storage layout?

[1] 
https://gitlab.arm.com/firmware/SCP-firmware/-/blob/v2.11.0/product/synquacer/include/fwu_mdata.h
[2] 
https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.7/include/drivers/fwu/fwu_metadata.h

Best regards,
Etienne

> From: Sughosh Ganu 
> 
> The following patches migrate the FWU metadata access code to version
> 2 of the structure. This is based on the structure definition as
> defined in the latest rev of the FWU Multi Bank Update specification
> [1].
> 
> Since the version 1 of the structure has currently been adopted on a
> couple of platforms, it was decided to have a clean migration of the
> metadata to version 2 only, instead of supporting both the versions of
> the structure. Also, based on consultations with the main author of
> the specification, it is expected that any further changes in the
> structure would be minor tweaks, and not be significant. Hence a
> migration to version 2.
> 
> Similar migration is also being done in TF-A, including migrating the
> ST platform port to support version 2 of the metadata structure [2].
> 
> @Michal, I tested the metadata for the two image per bank case, and it
> works fine on the ST board. Kindly test this on your board as well.
> 
> @Kojima-san, Please help in testing the version 2 on your
> board. Thanks.
> 
> 
> [1] - https://developer.arm.com/documentation/den0118/latest/
> [2] - 
> https://review.trustedfirmware.org/q/topic:%22topics/fwu_metadata_v2_migration%22
> 
> Changes since V1:
> 
> * Do not define flexible array members inside the structures.
> * Access the image information related fields in the metadata using
>   the helper functions defined in an earlier patch.
> * Access fwu_fw_store_desc structure using pointer arithmetic.
> 
> (snip)

[PATCH 2/2] tee: optee: don't enumerate services if there ain't any

2023-11-29 Thread Etienne Carriere
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, _list, _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, _list, _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



[PATCH 1/2] tee: optee: don't fail on services enumeration failure

2023-11-29 Thread Etienne Carriere
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



Re: [PATCH v6 08/14] firmware: scmi: add a version check against base protocol

2023-10-11 Thread Etienne CARRIERE - foss
> From: U-Boot  on behalf of AKASHI Takahiro 
> 
> Sent: Wednesday, October 11, 2023 12:07 PM
> 
> In SCMI base protocol version 2 (0x2), new interfaces,
> BASE_SET_DEVICE_PERMISSIONS/BASE_SET_PROTOCOL_PERMISSIONS/
> BASE_RESET_AGENT_CONFIGURATION, were added. Moreover, the api of
> BASE_DISCOVER_AGENT was changed to support self-agent discovery.
> 
> So the driver expects SCMI firmware support version 2 of base protocol.
> 
> Signed-off-by: AKASHI Takahiro 
> ---
> v6
> * new commit
> ---
>  drivers/firmware/scmi/base.c | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/firmware/scmi/base.c b/drivers/firmware/scmi/base.c
> index ee84e261945a..1d41a8a98fc6 100644
> --- a/drivers/firmware/scmi/base.c
> +++ b/drivers/firmware/scmi/base.c
> @@ -481,6 +481,7 @@ static int scmi_base_reset_agent_configuration_int(struct 
> udevice *dev,
>   */
>  static int scmi_base_probe(struct udevice *dev)
>  {
> +   u32 version;
> int ret;
> 
> ret = devm_scmi_of_get_channel(dev);
> @@ -488,6 +489,13 @@ static int scmi_base_probe(struct udevice *dev)
> dev_err(dev, "get_channel failed\n");
> return ret;
> }
> +   ret = scmi_base_protocol_version_int(dev, );
> +   if (ret) {
> +   dev_err(dev, "getting protocol version failed\n");
> +   return ret;
> +   }
> +   if (version < SCMI_BASE_PROTOCOL_VERSION)
> +   return -EINVAL;

LGTM. The open source SCMI server implementations I'm aware of (scp-firmware, 
tf-a and optee-os) all report SCMI Base protocol version v2.0.
Reviewed-by: Etienne Carriere 

That said, maybe a more flexible implementation would support both version v1.0 
(0x1) and v2.0
but disable permission commands for v1.0 compliant servers. Maybe in a later 
change, if there is a need for.
I fear using such strict minima protocol version values for other SCMI 
procotols make U-Boot client too restrictive.

BR,
Etienne

> 
> return ret;
>  }
> --
> 2.34.1
> 
> 


Re: [PATCH v5 04/16] test: dm: add protocol-specific channel test

2023-10-05 Thread Etienne CARRIERE - foss
> From: U-Boot  on behalf of Simon Glass 
> 
> Sent: Monday, October 2, 2023 3:17 AM
> 
> On Tue, 26 Sept 2023 at 00:58, AKASHI Takahiro
>  wrote:
> >
> > Any SCMI protocol may have its own channel.
> > Test this feature on sandbox as the necessary framework was added
> > in a prior commit.
> >
> > Signed-off-by: AKASHI Takahiro 
> > ---
> > v5
> > * new commit
> > ---
> >  arch/sandbox/dts/test.dts |  1 +
> >  test/dm/scmi.c| 20 ++--
> >  2 files changed, 19 insertions(+), 2 deletions(-)
> >
> 
> Reviewed-by: Simon Glass 
> 

Reviewed-by: Etienne Carriere 


Re: [PATCH v5 03/16] firmware: scmi: support dummy channels for sandbox agent

2023-10-05 Thread Etienne CARRIERE - foss
> 
> From: U-Boot  on behalf of Simon Glass 
> 
> Sent: Monday, October 2, 2023 3:17 AM
> 
> On Tue, 26 Sept 2023 at 00:58, AKASHI Takahiro
>  wrote:
> >
> > In sandbox scmi agent, channels are not used at all. But in this patch,
> > dummy channels are supported in order to test protocol-specific channels.
> >
> > Signed-off-by: AKASHI Takahiro 
> > ---
> > v5
> > * new commit
> > ---
> >  arch/sandbox/include/asm/scmi_test.h   | 13 
> >  drivers/firmware/scmi/sandbox-scmi_agent.c | 90 ++
> >  2 files changed, 103 insertions(+)
> >
> 
> Reviewed-by: Simon Glass 
> 

Reviewed-by: Etienne Carriere 


Re: [PATCH v5 02/16] firmware: scmi: use a protocol's own channel if assigned

2023-10-05 Thread Etienne CARRIERE - foss
> From: U-Boot  on behalf of AKASHI Takahiro 
> 
> Sent: Tuesday, September 26, 2023 8:57 AM
> 
> SCMI specification allows any protocol to have its own channel for
> the transport. While the current SCMI driver may assign its channel
> from a device tree, the core function, devm_scmi_process_msg(), doesn't
> use a protocol's channel, but always use an agent's channel.
> 
> With this commit, devm_scmi_process_msg() tries to find and use
> a protocol's channel. If it doesn't exist, use an agent's.
> 
> Signed-off-by: AKASHI Takahiro 
> ---
> v5
> * new commit (fixing a potential bug)
> ---
>  drivers/firmware/scmi/mailbox_agent.c | 5 +++--
>  drivers/firmware/scmi/optee_agent.c   | 5 +++--
>  drivers/firmware/scmi/scmi_agent-uclass.c | 7 ---
>  drivers/firmware/scmi/smccc_agent.c   | 5 +++--
>  include/scmi_agent-uclass.h   | 8 +---
>  5 files changed, 18 insertions(+), 12 deletions(-)
> 

Reviewed-by: Etienne Carriere 

Thanks for addressing this protocol channel issue.
BR,
Etienne

Re: [PATCH v5 01/16] scmi: refactor the code to hide a channel from devices

2023-10-05 Thread Etienne CARRIERE - foss
> From: U-Boot  on behalf of AKASHI Takahiro 
> 
> Sent: Tuesday, September 26, 2023 8:57 AM
> 
> 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 
> ---
> v5
> * correct the size for per_child_auto
> v4
> * revive scmi_bind_protocols which was accidentally removed
> * remove .per_child_auto from the driver declaration as it is not needed
> 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 | 105 --
>  drivers/power/regulator/scmi_regulator.c  |  26 ++
>  drivers/reset/reset-scmi.c|  19 +---
>  include/scmi_agent.h  |  15 ++--
>  5 files changed, 104 insertions(+), 88 deletions(-)
> 

Reviewed-by: Etienne Carriere 



Re: [PATCH v5 05/16] firmware: scmi: implement SCMI base protocol

2023-10-05 Thread Etienne CARRIERE - foss
Hello Akashi-san,


> From: U-Boot  on behalf of AKASHI Takahiro 
> 
> Sent: Tuesday, September 26, 2023 8:57 AM
> 
> 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 
> Reviewed-by: Simon Glass 
> ---
> v3
> * strncpy (TODO)
> * remove a duplicated function prototype
> * use newly-allocated memory when return vendor name or agent name
> * revise function descriptions in a header
> v2
> * add helper functions, removing direct uses of ops
> * add function descriptions for each of functions in ops
> ---

This patch v5 looks good to me. 2 suggestions.

Reviewed-by: Etienne Carriere  with comments 
addressed or not.
I have successfully tested the whole PATCH v5 series on my platform.



>  drivers/firmware/scmi/Makefile |   1 +
>  drivers/firmware/scmi/base.c   | 657 +
>  include/dm/uclass-id.h |   1 +
>  include/scmi_protocols.h   | 351 ++
>  4 files changed, 1010 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 ..dba143e1ff5d
> --- /dev/null
> +++ b/drivers/firmware/scmi/base.c
> @@ -0,0 +1,657 @@
> +// 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 
> +#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 on failure
> + */
> +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_msg_sz = sizeof(out),
> +   };
> +   int ret;
> +
> +   ret = devm_scmi_process_msg(dev, );
> +   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 on failure
> + */

I think these inline description comment for scmi_base_protocol_xxx_int()
would better be placed as description for the exported functions 
scmi_base_protocol_xxx() and scmi_base_discover_xxx(). Either in the .c file or 
in the header file.

Especially regarding the function 
scmi_base_discover_vendor()/_discover_sub_vendor()/_discover_agent() where 
caller is responsible for freeing the output string.


> +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

Re: [PATCH v3 13/13] test: dm: add scmi command test

2023-09-08 Thread Etienne CARRIERE
> 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,
> - );
> +   ret = scmi_base_protocol_message_attrs(base,
> +  SCMI_BASE_DISCOVER_SUB_VENDOR,
> +  );

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",
> + _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 v3 05/13] firmware: scmi: install base protocol to SCMI agent

2023-09-08 Thread Etienne CARRIERE
> 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 05/13] firmware: scmi: install base protocol to SCMI agent

2023-09-08 Thread Etienne CARRIERE
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, >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, >num_agents,
> +  >num_protocols);
> +   if (ret) {
> +   dev_err(dev, "protocol_attrs() failed (%d)\n", ret);
> +   return ret;
> +   }
> +   ret = scmi_base_discover_vendor(dev, >vendor);
> +   if (ret) {
> +   dev_err(dev, "base_discover_vendor() failed (%d)\n", ret);
> +   return ret;
> +   }
> +   ret = scmi_base_discover_sub_vendor(dev, >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, >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,
> +  >agent_id, >agent_name);
> +   if (ret) {
> +   if (ret != -EOPNOTSUPP) {
> +   dev_err(dev,
> +   "base_discover

Re: [PATCH v3 01/13] scmi: refactor the code to hide a channel from devices

2023-09-08 Thread Etienne CARRIERE
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, );
> +   ret = devm_scmi_process_msg(dev, );
>  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, );
> +   ret = devm_scmi_process_msg(dev, );
>  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, );
> +   ret = devm_scmi_process_msg(clk->dev, );
>  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, );
> +   ret = devm_scmi_process_msg(clk->dev, );
>  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, );
> +   ret = devm_scmi_process_msg(clk->dev, );
>  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);
>  struct clk *clk;
>  

Re: [PATCH v3 04/13] firmware: scmi: framework for installing additional protocols

2023-09-08 Thread Etienne CARRIERE

> 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 v2 01/12] scmi: refactor the code to hide a channel from devices

2023-08-08 Thread Etienne CARRIERE - foss
Hello Akashi-san,

> From: AKASHI Takahiro
> Sent: Monday, August 7, 2023 12:03 PM
> 
> Hi Etienne,
> 
> On Thu, Aug 03, 2023 at 09:24:51AM +, Etienne CARRIERE wrote:
> > 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, );
> > > +   ret = devm_scmi_process_msg(dev, );
> > > 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, );
> > > +   ret = devm_scmi_process_msg(dev, );
> > > 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, );
&g

Re: [RFC 3/3] firmware: scmi: add a sanity check against protocol version

2023-08-03 Thread Etienne CARRIERE
> 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,
> +   );
> +   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_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,
> +   );
> +   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,
> +   );
> +   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_ATTRIBUTES = 0x3,
>

Re: [RFC 2/3] firmware: scmi: add PROTOCOL_VERSION support for existing protocols on sandbox

2023-08-03 Thread Etienne CARRIERE
> 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 1/3] firmware: scmi: add a check against availability of protocols

2023-08-03 Thread Etienne CARRIERE
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: [PATCH v2 12/12] test: dm: add scmi command test

2023-08-03 Thread Etienne CARRIERE
> 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,
> - );
> +   ret = scmi_base_protocol_message_attrs(base,
> +  SCMI_BASE_DISCOVER_SUB_VENDOR,
> +  );
>  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",
> + _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: [PATCH v2 11/12] doc: cmd: add documentation for scmi

2023-08-03 Thread Etienne CARRIERE
> 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 10/12] cmd: add scmi command for SCMI firmware

2023-08-03 Thread Etienne CARRIERE
> 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 09/12] test: dm: add SCMI base protocol test

2023-08-03 Thread Etienne CARRIERE
> 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",
> +                                             _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, );
> +       ut_assertok(ret);
> +       ut_asserteq(priv->version, version);
> +
> +       /* protocol attributes */
> +       ret = scmi_base_protocol_attrs(base, _agents, _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,
> +                                         );
> +       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, _version);
> +       ut_assertok(ret);
> +       ut_asserteq(priv->impl_version, impl_version);
> +
> +       /* discover agent (my self) */
> +       ret = scmi_base_discover_agent(base, 0x, _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, );
> +       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_permissions(base, agent_id, 0, 0);
> +       ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
> +
&g

RE: [PATCH v2 08/12] test: dm: simplify SCMI unit test on sandbox

2023-08-03 Thread Etienne CARRIERE
> 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 _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)
> -{
> -   struct sandbox_scmi_service

RE: [PATCH v2 07/12] firmware: scmi: fake base protocol commands on sandbox

2023-08-03 Thread Etienne CARRIERE
> 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 06/12] sandbox: remove SCMI base node definition from test.dts

2023-08-03 Thread Etienne CARRIERE
> 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 05/12] firmware: scmi: install base protocol to SCMI agent

2023-08-03 Thread Etienne CARRIERE
> 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, >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, >num_agents,
> > > +  >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)

RE: [PATCH v2 04/12] firmware: scmi: framework for installing additional protocols

2023-08-03 Thread Etienne CARRIERE
> 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", _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_prot

RE: [PATCH v2 03/12] firmware: scmi: move scmi_bind_protocols() backward

2023-08-03 Thread Etienne CARRIERE
> 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", _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", _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:
> +

RE: [PATCH v2 02/12] firmware: scmi: implement SCMI base protocol

2023-08-03 Thread Etienne CARRIERE
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_msg_sz = sizeof(out),
> +       };
> +       int ret;
> +
> +       ret = devm_scmi_process_msg(dev, );
> +       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_msg_sz = sizeof(out),
> +       };
> +       int ret;
> +
> +       ret = devm_scmi_process_msg(dev, );
> +       if (ret)
> +               return ret;
> +       if (out.status)
> +               return scmi_

RE: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices

2023-08-03 Thread Etienne CARRIERE
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, );
> + ret = devm_scmi_process_msg(dev, );
>   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, );
> + ret = devm_scmi_process_msg(dev, );
>   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, );
> + ret = devm_scmi_process_msg(clk->dev, );
>   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, );
> + ret = devm_scmi_process_msg(clk->dev, );
>   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, );
> + ret = devm_scmi_process_msg(clk->dev, );
>   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)
>  {
> - 

Re: [PATCH v2 01/12] scmi: refactor the code to hide a channel from devices

2023-08-03 Thread Etienne CARRIERE - foss
Hello Takahiro-san,

> From: U-Boot  on behalf of Simon Glass 
> 
> Sent: Thursday, July 27, 2023 2:50 AM
> 
> On Wed, 26 Jul 2023 at 02:38, AKASHI Takahiro
>  wrote:
> >
> > 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(-)
> >
> 
> Reviewed-by: Simon Glass 

Sorry for this late feedback. I initially saw no issues with this patch series
but testing the series against stm32mp135f-dk board which is using SCMI
resources, I saw the board failed to boot. The issue is related to udevice
parent tree and common clock framework. I'll post comments on patch 01/12.

Best regards,
Etienne

Re: [PATCH v5 1/6] FWU: Add FWU metadata access driver for MTD storage regions

2023-04-11 Thread Etienne Carriere
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, _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(buf, 

Re: [PATCH v5 2/6] tools: Add mkfwumdata tool for FWU metadata image

2023-04-11 Thread Etienne Carriere
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 4/6] configs: move to new flash layout and boot flow

2023-04-11 Thread Etienne Carriere
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 5/6] fwu: DeveloperBox: add support for FWU

2023-04-11 Thread Etienne Carriere
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..

> 

Re: [PATCH v5 3/6] fwu: move meta-data management in core

2023-03-01 Thread Etienne Carriere
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 v5 4/6] fwu: gpt: implement read_mdata and write_mdata callbacks

2023-03-01 Thread Etienne Carriere
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: [PATCHv4 2/5] fwu: move meta-data management in core

2023-02-27 Thread Etienne Carriere
-   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: [PATCHv4 2/5] fwu: move meta-data management in core

2023-02-27 Thread Etienne Carriere
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 

Re: [PATCH v2] efi_loader: set CapsuleMax from CONFIG_EFI_CAPSULE_MAX

2023-02-16 Thread Etienne Carriere
On Thu, 16 Feb 2023 at 18:21, Etienne Carriere
 wrote:
>
> Adds CONFIG_EFI_CAPSULE_MAX to configure the max index value used in
> EFI capsule reports. The config default value is 65535 as the index max

I forgot to update the commit message.
I'll fix in v3.

> value used before this change. Platforms with limited storage capacity
> can set a lower configuration value to prevent storage capacity
> overflow or even waste of storage space.
>
> Signed-off-by: Etienne Carriere 
> ---
> Changes since v1
> - Changed CONFIG_EFI_CAPSULE_MAX default value from 65535 to 15.
> ---
>  lib/efi_loader/Kconfig   |  8 ++
>  lib/efi_loader/efi_capsule.c | 48 +---
>  lib/efi_loader/efi_setup.c   |  7 +-
>  3 files changed, 48 insertions(+), 15 deletions(-)
>
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index c56904afc2..727241dc9c 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -226,6 +226,14 @@ config EFI_CAPSULE_AUTHENTICATE
>   Select this option if you want to enable capsule
>   authentication
>
> +config EFI_CAPSULE_MAX
> +   int "Max value for capsule index"
> +   default 15
> +   range 0 65535
> +   help
> + Select the max capsule index value used for capsule report
> + variables. This value is used to create CapsuleMax variable.
> +
>  config EFI_DEVICE_PATH_TO_TEXT
> bool "Device path to text protocol"
> default y
> diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
> index 0997cd248f..d5d3ede7ae 100644
> --- a/lib/efi_loader/efi_capsule.c
> +++ b/lib/efi_loader/efi_capsule.c
> @@ -45,17 +45,7 @@ const efi_guid_t fwu_guid_os_request_fw_accept =
>  static struct efi_file_handle *bootdev_root;
>  #endif
>
> -/**
> - * get_last_capsule - get the last capsule index
> - *
> - * Retrieve the index of the capsule invoked last time from "CapsuleLast"
> - * variable.
> - *
> - * Return:
> - * * > 0   - the last capsule index invoked
> - * * 0x- on error, or no capsule invoked yet
> - */
> -static __maybe_unused unsigned int get_last_capsule(void)
> +static __maybe_unused unsigned int get_capsule_index(const u16 
> *variable_name)
>  {
> u16 value16[11]; /* "Capsule": non-null-terminated */
> char value[5];
> @@ -65,7 +55,7 @@ static __maybe_unused unsigned int get_last_capsule(void)
> int i;
>
> size = sizeof(value16);
> -   ret = efi_get_variable_int(u"CapsuleLast", _guid_capsule_report,
> +   ret = efi_get_variable_int(variable_name, _guid_capsule_report,
>NULL, , value16, NULL);
> if (ret != EFI_SUCCESS || size != 22 ||
> u16_strncmp(value16, u"Capsule", 7))
> @@ -84,6 +74,35 @@ err:
> return index;
>  }
>
> +/**
> + * get_last_capsule - get the last capsule index
> + *
> + * Retrieve the index of the capsule invoked last time from "CapsuleLast"
> + * variable.
> + *
> + * Return:
> + * * > 0   - the last capsule index invoked
> + * * 0x- on error, or no capsule invoked yet
> + */
> +static __maybe_unused unsigned int get_last_capsule(void)
> +{
> +   return get_capsule_index(u"CapsuleLast");
> +}
> +
> +/**
> + * get_max_capsule - get the max capsule index
> + *
> + * Retrieve the max capsule index value from "CapsuleMax" variable.
> + *
> + * Return:
> + * * > 0   - the max capsule index
> + * * 0x- on error, or "CapsuleMax" variable does not exist
> + */
> +static __maybe_unused unsigned int get_max_capsule(void)
> +{
> +   return get_capsule_index(u"CapsuleMax");
> +}
> +
>  /**
>   * set_capsule_result - set a result variable
>   * @capsule:   Capsule
> @@ -1290,7 +1309,7 @@ efi_status_t efi_launch_capsules(void)
>  {
> struct efi_capsule_header *capsule = NULL;
> u16 **files;
> -   unsigned int nfiles, index, i;
> +   unsigned int nfiles, index, index_max, i;
> efi_status_t ret;
> bool capsule_update = true;
> bool update_status = true;
> @@ -1299,6 +1318,7 @@ efi_status_t efi_launch_capsules(void)
> if (check_run_capsules() != EFI_SUCCESS)
> return EFI_SUCCESS;
>
> +   index_max = get_max_capsule();
> index = get_last_capsule();
>
> /*
> @@ -1317,7 +1337,7 @@ efi_status_t efi_launch_capsules(void)
> /* Launch capsules */
> for (i = 0, ++index; i < nfiles; i++, index++) {
>  

[PATCH v2] efi_loader: set CapsuleMax from CONFIG_EFI_CAPSULE_MAX

2023-02-16 Thread Etienne Carriere
Adds CONFIG_EFI_CAPSULE_MAX to configure the max index value used in
EFI capsule reports. The config default value is 65535 as the index max
value used before this change. Platforms with limited storage capacity
can set a lower configuration value to prevent storage capacity
overflow or even waste of storage space.

Signed-off-by: Etienne Carriere 
---
Changes since v1
- Changed CONFIG_EFI_CAPSULE_MAX default value from 65535 to 15.
---
 lib/efi_loader/Kconfig   |  8 ++
 lib/efi_loader/efi_capsule.c | 48 +---
 lib/efi_loader/efi_setup.c   |  7 +-
 3 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c56904afc2..727241dc9c 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -226,6 +226,14 @@ config EFI_CAPSULE_AUTHENTICATE
  Select this option if you want to enable capsule
  authentication
 
+config EFI_CAPSULE_MAX
+   int "Max value for capsule index"
+   default 15
+   range 0 65535
+   help
+ Select the max capsule index value used for capsule report
+ variables. This value is used to create CapsuleMax variable.
+
 config EFI_DEVICE_PATH_TO_TEXT
bool "Device path to text protocol"
default y
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 0997cd248f..d5d3ede7ae 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -45,17 +45,7 @@ const efi_guid_t fwu_guid_os_request_fw_accept =
 static struct efi_file_handle *bootdev_root;
 #endif
 
-/**
- * get_last_capsule - get the last capsule index
- *
- * Retrieve the index of the capsule invoked last time from "CapsuleLast"
- * variable.
- *
- * Return:
- * * > 0   - the last capsule index invoked
- * * 0x- on error, or no capsule invoked yet
- */
-static __maybe_unused unsigned int get_last_capsule(void)
+static __maybe_unused unsigned int get_capsule_index(const u16 *variable_name)
 {
u16 value16[11]; /* "Capsule": non-null-terminated */
char value[5];
@@ -65,7 +55,7 @@ static __maybe_unused unsigned int get_last_capsule(void)
int i;
 
size = sizeof(value16);
-   ret = efi_get_variable_int(u"CapsuleLast", _guid_capsule_report,
+   ret = efi_get_variable_int(variable_name, _guid_capsule_report,
   NULL, , value16, NULL);
if (ret != EFI_SUCCESS || size != 22 ||
u16_strncmp(value16, u"Capsule", 7))
@@ -84,6 +74,35 @@ err:
return index;
 }
 
+/**
+ * get_last_capsule - get the last capsule index
+ *
+ * Retrieve the index of the capsule invoked last time from "CapsuleLast"
+ * variable.
+ *
+ * Return:
+ * * > 0   - the last capsule index invoked
+ * * 0x- on error, or no capsule invoked yet
+ */
+static __maybe_unused unsigned int get_last_capsule(void)
+{
+   return get_capsule_index(u"CapsuleLast");
+}
+
+/**
+ * get_max_capsule - get the max capsule index
+ *
+ * Retrieve the max capsule index value from "CapsuleMax" variable.
+ *
+ * Return:
+ * * > 0   - the max capsule index
+ * * 0x- on error, or "CapsuleMax" variable does not exist
+ */
+static __maybe_unused unsigned int get_max_capsule(void)
+{
+   return get_capsule_index(u"CapsuleMax");
+}
+
 /**
  * set_capsule_result - set a result variable
  * @capsule:   Capsule
@@ -1290,7 +1309,7 @@ efi_status_t efi_launch_capsules(void)
 {
struct efi_capsule_header *capsule = NULL;
u16 **files;
-   unsigned int nfiles, index, i;
+   unsigned int nfiles, index, index_max, i;
efi_status_t ret;
bool capsule_update = true;
bool update_status = true;
@@ -1299,6 +1318,7 @@ efi_status_t efi_launch_capsules(void)
if (check_run_capsules() != EFI_SUCCESS)
return EFI_SUCCESS;
 
+   index_max = get_max_capsule();
index = get_last_capsule();
 
/*
@@ -1317,7 +1337,7 @@ efi_status_t efi_launch_capsules(void)
/* Launch capsules */
for (i = 0, ++index; i < nfiles; i++, index++) {
log_debug("Applying %ls\n", files[i]);
-   if (index > 0x)
+   if (index > index_max)
index = 0;
ret = efi_capsule_read_file(files[i], );
if (ret == EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index f0f01d3b1d..04da4cf14d 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -129,12 +129,17 @@ static efi_status_t efi_init_capsule(void)
efi_status_t ret = EFI_SUCCESS;
 
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) {
+   u16 var_name16[12];
+
+   efi_create_indexed_name(var_name16, sizeof(var_name

[PATCH] efi_loader: set CapsuleMax from CONFIG_EFI_CAPSULE_MAX

2023-02-16 Thread Etienne Carriere
Adds CONFIG_EFI_CAPSULE_MAX to configure the max index value used in
EFI capsule reports. The config default value is 65535 as the index max
value used before this change. Platforms with limited storage capacity
can set a lower configuration value to prevent storage capacity
overflow or even waste of storage space.

Signed-off-by: Etienne Carriere 
---
 lib/efi_loader/Kconfig   |  8 ++
 lib/efi_loader/efi_capsule.c | 48 +---
 lib/efi_loader/efi_setup.c   |  7 +-
 3 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c56904afc2..69bb66e09c 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -226,6 +226,14 @@ config EFI_CAPSULE_AUTHENTICATE
  Select this option if you want to enable capsule
  authentication
 
+config EFI_CAPSULE_MAX
+   int "Max value for capsule index"
+   default 65535
+   range 0 65535
+   help
+ Select the max capsule index value used for capsule report
+ variables. This value is used to create CapsuleMax variable.
+
 config EFI_DEVICE_PATH_TO_TEXT
bool "Device path to text protocol"
default y
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 0997cd248f..d5d3ede7ae 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -45,17 +45,7 @@ const efi_guid_t fwu_guid_os_request_fw_accept =
 static struct efi_file_handle *bootdev_root;
 #endif
 
-/**
- * get_last_capsule - get the last capsule index
- *
- * Retrieve the index of the capsule invoked last time from "CapsuleLast"
- * variable.
- *
- * Return:
- * * > 0   - the last capsule index invoked
- * * 0x- on error, or no capsule invoked yet
- */
-static __maybe_unused unsigned int get_last_capsule(void)
+static __maybe_unused unsigned int get_capsule_index(const u16 *variable_name)
 {
u16 value16[11]; /* "Capsule": non-null-terminated */
char value[5];
@@ -65,7 +55,7 @@ static __maybe_unused unsigned int get_last_capsule(void)
int i;
 
size = sizeof(value16);
-   ret = efi_get_variable_int(u"CapsuleLast", _guid_capsule_report,
+   ret = efi_get_variable_int(variable_name, _guid_capsule_report,
   NULL, , value16, NULL);
if (ret != EFI_SUCCESS || size != 22 ||
u16_strncmp(value16, u"Capsule", 7))
@@ -84,6 +74,35 @@ err:
return index;
 }
 
+/**
+ * get_last_capsule - get the last capsule index
+ *
+ * Retrieve the index of the capsule invoked last time from "CapsuleLast"
+ * variable.
+ *
+ * Return:
+ * * > 0   - the last capsule index invoked
+ * * 0x- on error, or no capsule invoked yet
+ */
+static __maybe_unused unsigned int get_last_capsule(void)
+{
+   return get_capsule_index(u"CapsuleLast");
+}
+
+/**
+ * get_max_capsule - get the max capsule index
+ *
+ * Retrieve the max capsule index value from "CapsuleMax" variable.
+ *
+ * Return:
+ * * > 0   - the max capsule index
+ * * 0x- on error, or "CapsuleMax" variable does not exist
+ */
+static __maybe_unused unsigned int get_max_capsule(void)
+{
+   return get_capsule_index(u"CapsuleMax");
+}
+
 /**
  * set_capsule_result - set a result variable
  * @capsule:   Capsule
@@ -1290,7 +1309,7 @@ efi_status_t efi_launch_capsules(void)
 {
struct efi_capsule_header *capsule = NULL;
u16 **files;
-   unsigned int nfiles, index, i;
+   unsigned int nfiles, index, index_max, i;
efi_status_t ret;
bool capsule_update = true;
bool update_status = true;
@@ -1299,6 +1318,7 @@ efi_status_t efi_launch_capsules(void)
if (check_run_capsules() != EFI_SUCCESS)
return EFI_SUCCESS;
 
+   index_max = get_max_capsule();
index = get_last_capsule();
 
/*
@@ -1317,7 +1337,7 @@ efi_status_t efi_launch_capsules(void)
/* Launch capsules */
for (i = 0, ++index; i < nfiles; i++, index++) {
log_debug("Applying %ls\n", files[i]);
-   if (index > 0x)
+   if (index > index_max)
index = 0;
ret = efi_capsule_read_file(files[i], );
if (ret == EFI_SUCCESS) {
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index f0f01d3b1d..04da4cf14d 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -129,12 +129,17 @@ static efi_status_t efi_init_capsule(void)
efi_status_t ret = EFI_SUCCESS;
 
if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) {
+   u16 var_name16[12];
+
+   efi_create_indexed_name(var_name16, sizeof(var_name16),
+   "Capsule", 

[PATCH v2] efi_loader: Measure the loaded DTB

2023-02-16 Thread Etienne Carriere
Measures the DTB passed to the EFI application upon new boolean config
switch CONFIG_EFI_TCG2_PROTOCOL_MEASURE_DTB. For platforms where the
content of the DTB passed to the OS can change across reboots, there is
not point measuring it hence the config switch to allow platform to not
embed this feature.

Co-developed-by: Ilias Apalodimas 
Signed-off-by: Ilias Apalodimas 
Signed-off-by: Etienne Carriere 
---
Changes since v1
- Moved measurement to after DTB tweaks in efi_install_fdt() and change
  its measure to hash only populated areas in the DTB (header, structs,
  strings and reserved memory maps). efi_tcg2_measure_dtb() computes
  the hash of these concatenated areas and used it as DTB  measurement.
- Remove useless default value 'n' for EFI_TCG2_PROTOCOL_MEASURE_DTB.
- I did not add EFI_TCG2_PROTOCOL_MEASURE_DTB dependencies on
  !NET_RANDOM_ETHADDR neither on !CMD_KASLRSEED. If ethernet address
  is random but always the same at each boot as saved in environment,
  it's measure is meaningful. CMD_KASLRSEED effect in DT if already
  addressed by efi_try_purge_kaslr_seed() prior measurement.
---
 cmd/bootefi.c |  8 +
 include/efi_loader.h  |  2 ++
 include/efi_tcg2.h| 10 ++
 include/tpm-v2.h  |  2 ++
 lib/efi_loader/Kconfig| 11 ++
 lib/efi_loader/efi_tcg2.c | 73 +++
 6 files changed, 106 insertions(+)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 2a7d42925d..6618335ddf 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -332,6 +332,14 @@ efi_status_t efi_install_fdt(void *fdt)
 
efi_try_purge_kaslr_seed(fdt);
 
+   if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
+   ret = efi_tcg2_measure_dtb(fdt);
+   if (ret == EFI_SECURITY_VIOLATION) {
+   log_err("ERROR: failed to measure DTB\n");
+   return ret;
+   }
+   }
+
/* Install device tree as UEFI table */
ret = efi_install_configuration_table(_guid_fdt, fdt);
if (ret != EFI_SUCCESS) {
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 4560b0d04c..4ecfdf919b 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -531,6 +531,8 @@ efi_status_t 
efi_tcg2_notify_exit_boot_services_failed(void);
 efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj 
*handle);
 /* Measure efi application exit */
 efi_status_t efi_tcg2_measure_efi_app_exit(void);
+/* Measure DTB */
+efi_status_t efi_tcg2_measure_dtb(void *dtb);
 /* Called by bootefi to initialize root node */
 efi_status_t efi_root_node_register(void);
 /* Called by bootefi to initialize runtime */
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index 874306dc11..b1c3abd097 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -233,6 +233,16 @@ struct efi_gpt_data {
gpt_entry partitions[];
 } __packed;
 
+/**
+ * struct tdUEFI_PLATFORM_FIRMWARE_BLOB2
+ * @blob_description_size: Byte size of @data
+ * @data:  Description data
+ */
+struct uefi_platform_firmware_blob2 {
+   u8 blob_description_size;
+   u8 data[];
+} __packed;
+
 struct efi_tcg2_protocol {
efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
   struct 
efi_tcg2_boot_service_capability *capability);
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 737e57551d..2df3dad553 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -105,6 +105,8 @@ struct udevice;
"Exit Boot Services Returned with Failure"
 #define EFI_EXIT_BOOT_SERVICES_SUCCEEDED\
"Exit Boot Services Returned with Success"
+#define EFI_DTB_EVENT_STRING \
+   "DTB DATA"
 
 /* TPMS_TAGGED_PROPERTY Structure */
 struct tpms_tagged_property {
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index c56904afc2..c05a54df16 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -346,6 +346,17 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
this is going to be allocated twice. One for the eventlog it 
self
and one for the configuration table that is required from the 
spec
 
+config EFI_TCG2_PROTOCOL_MEASURE_DTB
+   bool "Measure DTB with EFI_TCG2_PROTOCOL"
+   depends on EFI_TCG2_PROTOCOL
+   help
+ When enabled, the DTB image passed to the booted EFI image is
+ measured using the EFI TCG2 protocol. Do not enable this feature if
+ the passed DTB contains data that change across platform reboots
+ and cannot be used has a predictable measurement. Otherwise
+ this feature allows better measurement of the system boot
+ sequence.
+
 config EFI_LOAD_FILE2_INITRD
bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
default y
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 918e9a2686.

Re: [PATCH 1/1] efi_loader: stop watchdogs in ExitBootServices()

2023-02-02 Thread Etienne Carriere
Hello Heinrich and all,

On Wed, 1 Feb 2023 at 10:00, Heinrich Schuchardt
 wrote:
>
>
>
> On 2/1/23 09:32, Rasmus Villemoes wrote:
> > On 31/01/2023 16.07, Tom Rini wrote:
> >> On Tue, Jan 31, 2023 at 02:03:10PM +0200, Ilias Apalodimas wrote:
> >>> Hi all,
> >>>
> >>> On Mon, Jan 30, 2023 at 01:30:49PM -0500, Tom Rini wrote:
>  On Mon, Jan 30, 2023 at 01:13:55PM -0500, Tom Rini wrote:
> > On Sat, Jan 28, 2023 at 09:57:45AM +0100, Heinrich Schuchardt wrote:
> >
> >> The UEFI specification requires for ExitBootServices() that "the boot
> >> services watchdog timer is disabled". We already disable the software
> >> watchdog. We should additionally disable the hardware watchdogs.
> >>
> >> Reported-by: Andre Przywara 
> >> Signed-off-by: Heinrich Schuchardt 
> >> ---
> >>   lib/efi_loader/efi_boottime.c | 10 ++
> >>   1 file changed, 6 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/lib/efi_loader/efi_boottime.c 
> >> b/lib/efi_loader/efi_boottime.c
> >> index ba28989f36..71215af9d2 100644
> >> --- a/lib/efi_loader/efi_boottime.c
> >> +++ b/lib/efi_loader/efi_boottime.c
> >> @@ -19,6 +19,7 @@
> >>   #include 
> >>   #include 
> >>   #include 
> >> +#include 
> >>   #include 
> >>   #include 
> >>   #include 
> >> @@ -2171,6 +2172,11 @@ static efi_status_t EFIAPI 
> >> efi_exit_boot_services(efi_handle_t image_handle,
> >>  list_del(>link);
> >>  }
> >>
> >> +/* Disable watchdogs */
> >> +efi_set_watchdog(0);
> >> +if IS_ENABLED(CONFIG_WDT)
> >> +wdt_stop_all();
> >> +
> >>  if (!efi_st_keep_devices) {
> >>  bootm_disable_interrupts();
> >>  if (IS_ENABLED(CONFIG_USB_DEVICE))
> >> @@ -2196,10 +2202,6 @@ static efi_status_t EFIAPI 
> >> efi_exit_boot_services(efi_handle_t image_handle,
> >>
> >>  /* Recalculate CRC32 */
> >>  efi_update_table_header_crc32();
> >> -
> >> -/* Give the payload some time to boot */
> >> -efi_set_watchdog(0);
> >> -schedule();
> >>   out:
> >>  if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
> >>  if (ret != EFI_SUCCESS)
> >
> > I thought we had rejected going down this path since the UEFI spec is
> > unhelpfully wrong if it insists this?
> 
>  Because, to be clear, stopping hardware watchdogs is not to be done. The
>  one in-tree caller of wdt_stop_all is very questionable. You cannot
>  seriously stop a watchdog until someone else can hopefully resume it as
>  that violates the function of a hardware watchdog. A pure software
>  watchdog is one thing, and a hardware watchdog is another. I feel like
>  the most likely answer here is that someone needs to, still, push back
>  to the UEFI specification to get hardware watchdogs better understood
>  and handled, as it must never be stopped once started and if you cannot
>  reach the next stage in time, that's an engineering issue to resolve. My
>  first guess is that ExitBootServices should service the watchdog one
>  last time to ensure the largest window of time for the OS to take over
>  servicing of the watchdog.
> 
> >>>
> >>> There's two scenarios I can think of
> >>> 1. After U-Boot is done it can disable the hardware watchdog.
> >>> The kernel will go through the EFI-stub -> kernel proper -> watchdog
> >>> gets re-initialized.  In that case you are *hoping* that device won't
> >>> hang in the efi-stub or until the wd is up again.
> >>> 2. EFI makes sure the hardware wd gets configured with the highest allowed
> >>> value.  The efi-stub doesn't have any driver to refresh the wd, so we
> >>> will again rely on the wd driver coming up and refreshing the timers.
> >>
> >> You cannot stop the hardware watchdog, period. I think in the previous
> >> thread about this it was noted that some hardware watchdogs cannot be
> >> disabled, it's not function that the watchdog supports. Someone needs to
> >> go and talk with the UEFI specification people and get this addressed.
> >> There is no sane path for "disable the hardware watchdog".
> >>
> >
> > Indeed.
> >
> > But I think one reasonable thing to do would be to say "ok, the payload
> > is now ready to assume responsibility, so on the U-Boot side we stop
> > _petting_ the watchdog(s)" (i.e. nowadays that would mean deregistering
> > them from the cyclic framework), even if the payload still performs
> > calls into U-Boot where we would otherwise use the opportunity to feed
> > the watchdog. And of course it's reasonable in that case to do one last
> > ping. Because it's also a recipe for disaster if, say, both the payload
> > and U-Boot toggles the same gpio or frobs the same SOC registers.
> >
> > Unrelated, but does 

Re: [PATCH] efi_loader: silence 'Failed to load EFI variables' if the file is missing

2023-01-20 Thread Etienne Carriere
On Thu, 19 Jan 2023 at 14:47, Ilias Apalodimas
 wrote:
>
> Right,
> I'll answer to myself here.
>
> On Thu, 19 Jan 2023 at 15:26, Ilias Apalodimas
>  wrote:
> >
> > Hi Etienne,
> >
> > On Thu, 19 Jan 2023 at 15:15, Etienne Carriere
> >  wrote:
> > >
> > > On Thu, 19 Jan 2023 at 13:53, Ilias Apalodimas
> > >  wrote:
> > > >
> > > > Hi Heinrich,
> > > > On Thu, Jan 19, 2023 at 01:42:20PM +0100, Heinrich Schuchardt wrote:
> > > > > On 1/19/23 12:45, Ilias Apalodimas wrote:
> > > > > > Hi Etienne,
> > > > > >
> > > > > > On Thu, 19 Jan 2023 at 13:17, Etienne Carriere
> > > > > >  wrote:
> > > > > > >
> > > > > > > On Wed, 18 Jan 2023 at 17:12, Ilias Apalodimas
> > > > > > >  wrote:
> > > > > > > >
> > > > > > > > When we try to load EFI variables from a file in the ESP 
> > > > > > > > partition and the
> > > > > > > > file is missing We print a scary error looking like
> > > > > > > > => printenv -e
> > > > > > > > ** Unable to read file ubootefi.var **
> > > > >
> > > > > This message is in line fs/fat/fat.c:1297:
> > > > > printf("** Unable to read file %s **\n", filename);
> > > > >
> > > > > The message is misplaced. If any message is written, it should be in
> > > > > fat_read_at().
> > > > >
> > > > > But I think fat_read_at() should also be quiet. It is the task of the
> > > > > calling application to shout out if a file cannot be read.
> > > > >
> > > > > I have not checked if a test in test/py/tests/test_fs/ relies on the
> > > > > error message.
> > > > >
> > > > > > > > Failed to load EFI variables
> > > > >
> > > > > If there is a writable ESP, file ubootefi.var is created on first 
> > > > > boot.
> > > >
> > > > Are you sure?  I think it's created the moment you create an EFI 
> > > > variable.
> > > > So on a board that uses preseeded files you'll always see the message.
> > >
> > > It's created once EFI variables are loaded from preseed.
> > > Later boots load the variables from the file.
> >
> > Unless I am missing something, efi_set_variable_int() is the only
> > caller of efi_var_to_file() which creates that file. That only gets
> > called when a call to SetVariable is made.
> >
>
> We do set the PlatformLang on u-boot.  But as Heinrich pointed out,
> there's a check in that setvariable that shouldn't be there
> (efi_obj_list_initialized == EFI_SUCCESS).  So the file ends up not
> being created

Ok, I saw the patch in the ML.
Thanks for the details.

etienne

>
> Cheers
> /Ilias
> > Regards
> > /Ilias
> > >
> > > >
> > > > Thanks
> > > > /Ilias
> > > > > So this message should only once in the lifecycle of the board.
> > > > >
> > > > > Afterwards this message indicates that something is really wrong.
> > > > >
> > > > > If board vendors doesn't like it, they can create a dummy file.
> > > > >
> > > > > Best regards
> > > > >
> > > > > Heinrich
> > > > >
> > > > > > > >
> > > > > > > > This is not an error though since the file wasn't there to 
> > > > > > > > begin with.
> > > > > > > > So silence the warning by aborting the load if the file is not 
> > > > > > > > there,
> > > > > > > > instead of failing the load.
> > > > > > > >
> > > > > > > > Signed-off-by: Ilias Apalodimas 
> > > > > > > > ---
> > > > > > > >   lib/efi_loader/efi_var_file.c | 6 ++
> > > > > > > >   1 file changed, 6 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/lib/efi_loader/efi_var_file.c 
> > > > > > > > b/lib/efi_loader/efi_var_file.c
> > > > > > > > index 62e071bd8341..7d7141473634 100644
> > > > > > > > --- a/lib/efi_loader/efi_var_file.c
> > > > > > > > +++ b/lib/efi_loader/efi_var_file.c
> > > > > > > > @@ -223,6 +223,12 @@ efi_status_t efi_var_from_file(void)
> > > > > > > >  return EFI_OUT_OF_RESOURCES;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +   ret = efi_set_blk_dev_to_system_partition();
> > > > > > > > +   if (ret != EFI_SUCCESS)
> > > > > > > > +   goto error;
> > > > > > > > +   if (!fs_exists(EFI_VAR_FILE_NAME))
> > > > > > > > +   goto error;
> > > > > > > > +
> > > > > > > >  ret = efi_set_blk_dev_to_system_partition();
> > > > > > > >  if (ret != EFI_SUCCESS)
> > > > > > > >  goto error;
> > > > > > >
> > > > > > > This later call to efi_set_blk_dev_to_system_partition() can be
> > > > > > > removed since already done above.
> > > > > > >
> > > > > >
> > > > > > iirc fs_exists() unconditionally calls fs_close() so we need that 
> > > > > > double call
> > > > > >
> > > > > > Cheers
> > > > > > /Ilias
> > > > > > > Etienne
> > > > > > >
> > > > > > > > --
> > > > > > > > 2.38.1
> > > > > > > >
> > > > >


Re: [PATCH] tpm2: ftpm: add the device in the OP-TEE services list

2023-01-19 Thread Etienne Carriere
On Thu, 19 Jan 2023 at 16:11, Jens Wiklander  wrote:
>
> On Thu, Jan 19, 2023 at 3:36 PM Ilias Apalodimas
>  wrote:
> >
> > commit fe8a4ed0111073 ("tee: optee: discover services dependent on 
> > tee-supplicant")
> > is trying to automatically scan and add TAs that are presented on pseudo
> > bus from the secure world.
> > In orer to be able to list and compare the scanned devices the available 
> > drivers
> In order to...
>
> > have to register themselves on the op-tee service list.
> >
> > Signed-off-by: Ilias Apalodimas 
> > ---
> >  drivers/tpm/tpm2_ftpm_tee.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/tpm/tpm2_ftpm_tee.c b/drivers/tpm/tpm2_ftpm_tee.c
> > index 3c4c12983daa..f0deaec5b076 100644
> > --- a/drivers/tpm/tpm2_ftpm_tee.c
> > +++ b/drivers/tpm/tpm2_ftpm_tee.c
> > @@ -18,10 +18,12 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include "tpm_tis.h"
> >  #include "tpm2_ftpm_tee.h"
> >
> > +OPTEE_SERVICE_DRIVER(optee_ftpm, TA_FTPM_UUID, "ftpm_tee");
> >  /**

Add an empty line between the 2 above lines.
With that fixed and Jens' comment addressed,
Acked-by: Etienne Carriere 

> >   * ftpm_tee_transceive() - send fTPM commands and retrieve fTPM response.
> >   * @sendbuf - address of the data to send, byte by byte
> > --
> > 2.38.1
> >
>
> With the spelling error in the commit message fixed.
>
> Reviewed-by: Jens Wiklander 
>
> Cheers,
> Jens


Re: [PATCH] tee: optee: fix uuid comparisons on service discovery

2023-01-19 Thread Etienne Carriere
On Thu, 19 Jan 2023 at 10:21, Ilias Apalodimas
 wrote:
>
> When comparing UUIDs for discovered services we only compare up to the
> ptr size instead of the entire UUID
>
> Fixes: 94ccfb78a4d61 ("drivers: tee: optee: discover OP-TEE services")
> Signed-off-by: Ilias Apalodimas 
> ---
>  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 88e23d252bcd..9a9b697e91f5 100644
> --- a/drivers/tee/optee/core.c
> +++ b/drivers/tee/optee/core.c
> @@ -73,7 +73,7 @@ static struct optee_service *find_service_driver(const 
> struct tee_optee_ta_uuid
>
> for (idx = 0; idx < service_cnt; idx++, service++) {
> tee_optee_ta_uuid_to_octets(loc_uuid, >uuid);
> -   if (!memcmp(uuid, loc_uuid, sizeof(uuid)))
> +   if (!memcmp(uuid, loc_uuid, sizeof(*uuid)))
>         return service;
> }
>
> --
> 2.38.1
>

Reviewed-by: Etienne Carriere 


Re: [PATCH] efi_loader: silence 'Failed to load EFI variables' if the file is missing

2023-01-19 Thread Etienne Carriere
On Thu, 19 Jan 2023 at 13:53, Ilias Apalodimas
 wrote:
>
> Hi Heinrich,
> On Thu, Jan 19, 2023 at 01:42:20PM +0100, Heinrich Schuchardt wrote:
> > On 1/19/23 12:45, Ilias Apalodimas wrote:
> > > Hi Etienne,
> > >
> > > On Thu, 19 Jan 2023 at 13:17, Etienne Carriere
> > >  wrote:
> > > >
> > > > On Wed, 18 Jan 2023 at 17:12, Ilias Apalodimas
> > > >  wrote:
> > > > >
> > > > > When we try to load EFI variables from a file in the ESP partition 
> > > > > and the
> > > > > file is missing We print a scary error looking like
> > > > > => printenv -e
> > > > > ** Unable to read file ubootefi.var **
> >
> > This message is in line fs/fat/fat.c:1297:
> > printf("** Unable to read file %s **\n", filename);
> >
> > The message is misplaced. If any message is written, it should be in
> > fat_read_at().
> >
> > But I think fat_read_at() should also be quiet. It is the task of the
> > calling application to shout out if a file cannot be read.
> >
> > I have not checked if a test in test/py/tests/test_fs/ relies on the
> > error message.
> >
> > > > > Failed to load EFI variables
> >
> > If there is a writable ESP, file ubootefi.var is created on first boot.
>
> Are you sure?  I think it's created the moment you create an EFI variable.
> So on a board that uses preseeded files you'll always see the message.

It's created once EFI variables are loaded from preseed.
Later boots load the variables from the file.

>
> Thanks
> /Ilias
> > So this message should only once in the lifecycle of the board.
> >
> > Afterwards this message indicates that something is really wrong.
> >
> > If board vendors doesn't like it, they can create a dummy file.
> >
> > Best regards
> >
> > Heinrich
> >
> > > > >
> > > > > This is not an error though since the file wasn't there to begin with.
> > > > > So silence the warning by aborting the load if the file is not there,
> > > > > instead of failing the load.
> > > > >
> > > > > Signed-off-by: Ilias Apalodimas 
> > > > > ---
> > > > >   lib/efi_loader/efi_var_file.c | 6 ++
> > > > >   1 file changed, 6 insertions(+)
> > > > >
> > > > > diff --git a/lib/efi_loader/efi_var_file.c 
> > > > > b/lib/efi_loader/efi_var_file.c
> > > > > index 62e071bd8341..7d7141473634 100644
> > > > > --- a/lib/efi_loader/efi_var_file.c
> > > > > +++ b/lib/efi_loader/efi_var_file.c
> > > > > @@ -223,6 +223,12 @@ efi_status_t efi_var_from_file(void)
> > > > >  return EFI_OUT_OF_RESOURCES;
> > > > >  }
> > > > >
> > > > > +   ret = efi_set_blk_dev_to_system_partition();
> > > > > +   if (ret != EFI_SUCCESS)
> > > > > +   goto error;
> > > > > +   if (!fs_exists(EFI_VAR_FILE_NAME))
> > > > > +   goto error;
> > > > > +
> > > > >  ret = efi_set_blk_dev_to_system_partition();
> > > > >  if (ret != EFI_SUCCESS)
> > > > >  goto error;
> > > >
> > > > This later call to efi_set_blk_dev_to_system_partition() can be
> > > > removed since already done above.
> > > >
> > >
> > > iirc fs_exists() unconditionally calls fs_close() so we need that double 
> > > call
> > >
> > > Cheers
> > > /Ilias
> > > > Etienne
> > > >
> > > > > --
> > > > > 2.38.1
> > > > >
> >


Re: [PATCH] efi_loader: silence 'Failed to load EFI variables' if the file is missing

2023-01-19 Thread Etienne Carriere
On Thu, 19 Jan 2023 at 12:46, Ilias Apalodimas
 wrote:
>
> Hi Etienne,
>
> On Thu, 19 Jan 2023 at 13:17, Etienne Carriere
>  wrote:
> >
> > On Wed, 18 Jan 2023 at 17:12, Ilias Apalodimas
> >  wrote:
> > >
> > > When we try to load EFI variables from a file in the ESP partition and the
> > > file is missing We print a scary error looking like
> > > => printenv -e
> > > ** Unable to read file ubootefi.var **
> > > Failed to load EFI variables
> > >
> > > This is not an error though since the file wasn't there to begin with.
> > > So silence the warning by aborting the load if the file is not there,
> > > instead of failing the load.
> > >
> > > Signed-off-by: Ilias Apalodimas 
> > > ---
> > >  lib/efi_loader/efi_var_file.c | 6 ++
> > >  1 file changed, 6 insertions(+)
> > >
> > > diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c
> > > index 62e071bd8341..7d7141473634 100644
> > > --- a/lib/efi_loader/efi_var_file.c
> > > +++ b/lib/efi_loader/efi_var_file.c
> > > @@ -223,6 +223,12 @@ efi_status_t efi_var_from_file(void)
> > > return EFI_OUT_OF_RESOURCES;
> > > }
> > >
> > > +   ret = efi_set_blk_dev_to_system_partition();
> > > +   if (ret != EFI_SUCCESS)
> > > +   goto error;
> > > +   if (!fs_exists(EFI_VAR_FILE_NAME))
> > > +   goto error;
> > > +
> > > ret = efi_set_blk_dev_to_system_partition();
> > > if (ret != EFI_SUCCESS)
> > > goto error;
> >
> > This later call to efi_set_blk_dev_to_system_partition() can be
> > removed since already done above.
> >
>
> iirc fs_exists() unconditionally calls fs_close() so we need that double call

Ok. Sorry.

etienne

>
> Cheers
> /Ilias
> > Etienne
> >
> > > --
> > > 2.38.1
> > >


Re: [PATCH] efi_loader: silence 'Failed to load EFI variables' if the file is missing

2023-01-19 Thread Etienne Carriere
On Wed, 18 Jan 2023 at 17:12, Ilias Apalodimas
 wrote:
>
> When we try to load EFI variables from a file in the ESP partition and the
> file is missing We print a scary error looking like
> => printenv -e
> ** Unable to read file ubootefi.var **
> Failed to load EFI variables
>
> This is not an error though since the file wasn't there to begin with.
> So silence the warning by aborting the load if the file is not there,
> instead of failing the load.
>
> Signed-off-by: Ilias Apalodimas 
> ---
>  lib/efi_loader/efi_var_file.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c
> index 62e071bd8341..7d7141473634 100644
> --- a/lib/efi_loader/efi_var_file.c
> +++ b/lib/efi_loader/efi_var_file.c
> @@ -223,6 +223,12 @@ efi_status_t efi_var_from_file(void)
> return EFI_OUT_OF_RESOURCES;
> }
>
> +   ret = efi_set_blk_dev_to_system_partition();
> +   if (ret != EFI_SUCCESS)
> +   goto error;
> +   if (!fs_exists(EFI_VAR_FILE_NAME))
> +   goto error;
> +
> ret = efi_set_blk_dev_to_system_partition();
> if (ret != EFI_SUCCESS)
> goto error;

This later call to efi_set_blk_dev_to_system_partition() can be
removed since already done above.

Etienne

> --
> 2.38.1
>


Re: [PATCH] tee: optee: fix a print error on rng probing

2023-01-18 Thread Etienne Carriere
On Wed, 18 Jan 2023 at 19:54, Ilias Apalodimas
 wrote:
>
> Thanks Patrick,
>
> On Wed, 18 Jan 2023 at 18:53, Patrick DELAUNAY
>  wrote:
> >
> > Hi
> >
> > On 1/18/23 16:38, Ilias Apalodimas wrote:
> > > If we fail to probe the optee-rng device, we print a wrong message
> > > referring to the firmware tpm.
> > >
> > > Signed-off-by: Ilias Apalodimas 
> > > ---
> > >   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 a813a84a4f16..88e23d252bcd 100644
> > > --- a/drivers/tee/optee/core.c
> > > +++ b/drivers/tee/optee/core.c
> > > @@ -850,7 +850,7 @@ static int optee_probe(struct udevice *dev)
> > >   ret = device_bind_driver_to_node(dev, "optee-rng", 
> > > "optee-rng",
> > >dev_ofnode(dev), NULL);
> > >   if (ret)
> > > - dev_warn(dev, "ftpm_tee failed to bind: %d\n", ret);
> > > + dev_warn(dev, "optee-rng failed to bind: %d\n", 
> > > ret);
> > >   }
> > >
> > >   return 0;
> >
> >
> > I think you can add:
> >
> > Fixes: 476a3d58dfeb ("tee: optee: don't fail probe because of optee-rng")
> >
> >
> > Reviewed-by: Patrick Delaunay 
>
> Sure I'll wait for additional reviews etc and respin

Reviewed-by: Etienne Carriere 
Sorry for that :|

etienne

>
> Cheers
> /Ilias
> >
> > Thanks
> > Patrick
> >
> >


Re: [PATCHv2 1/4] fwu: gpt: use cached meta-data partition numbers

2023-01-04 Thread Etienne Carriere
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, ))
> > >   continue;
> > >   uuid_str_to_bin(info.type_guid, part_type_guid.b,
> > >   UUID_STR_FORMAT_GUID);
> > >
> > > - if (!guidcmp(_mdata_guid, _type_guid)) {
> > > - if (nparts < 2)
> > > - mdata_parts[nparts] = i;
> > > - ++nparts;
> > > - }
> > > + if (!guidcmp(_mdata_guid, _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


Re: [PATCH 3/3] bootm: Support boot measurement

2023-01-04 Thread Etienne Carriere
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, , 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 3/4] fwu: gpt: implement read_mdata and write_mdata callbacks

2023-01-02 Thread Etienne Carriere
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: [PATCHv2 4/4] fwu: meta-data: switch to management by common code

2023-01-02 Thread Etienne Carriere
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) {
> -   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, );
> +   res = fwu_get_verified_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)
> -{
> -   const str

Re: [PATCHv2 5/4] fwu: rename fwu_get_verified_mdata to fwu_get_mdata

2023-01-02 Thread Etienne Carriere
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();
> +   res = fwu_get_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 2/4] fwu: move meta-data management in core

2022-12-13 Thread Etienne Carriere
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 

Re: [PATCH] efi_loader: Measure the loaded DTB

2022-12-08 Thread Etienne Carriere
Hello Heinrich and all,

Thanks for the feedback.

On Thu, 8 Dec 2022 at 10:10, Heinrich Schuchardt  wrote:
>
> Am 8. Dezember 2022 09:01:26 MEZ schrieb Ilias Apalodimas 
> :
> >Hi Heinrich
> >
> >On Thu, Dec 08, 2022 at 05:12:26AM +0100, Heinrich Schuchardt wrote:
> >> On 12/7/22 16:11, Etienne Carriere wrote:
> >> > Measures the DTB passed to the EFI application upon new boolean config
> >> > switch CONFIG_EFI_TCG2_PROTOCOL_MEASURE_DTB. For platforms where the
> >> > content of the DTB passed to the OS can change across reboots, there is
> >> > not point measuring it hence the config switch to allow platform to not
> >> > embed this feature.
> >> >
> >> > Co-developed-by: Ilias Apalodimas 
> >> > Signed-off-by: Ilias Apalodimas 
> >> > Signed-off-by: Etienne Carriere 
> >> > ---
> >> >   cmd/bootefi.c |  9 +
> >> >   include/efi_loader.h  |  2 ++
> >> >   include/efi_tcg2.h| 10 ++
> >> >   include/tpm-v2.h  |  2 ++
> >> >   lib/efi_loader/Kconfig| 12 
> >> >   lib/efi_loader/efi_tcg2.c | 36 
> >> >   6 files changed, 71 insertions(+)
> >> >
> >> > diff --git a/cmd/bootefi.c b/cmd/bootefi.c
> >> > index 2a7d42925d..56e4a1909f 100644
> >> > --- a/cmd/bootefi.c
> >> > +++ b/cmd/bootefi.c
> >> > @@ -315,6 +315,15 @@ efi_status_t efi_install_fdt(void *fdt)
> >> >return EFI_LOAD_ERROR;
> >> >}
> >> >
> >> > +  /* Measure the installed DTB */
> >> > +  if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
> >> > +  ret = efi_tcg2_measure_dtb(fdt);
> >>
> >> Why measure here and not in efi_tcg2_measure_efi_app_invocation() where
> >> we measure the SMBIOS table every time when an app is started with
> >> StartImage()? Which may mean measuring it multiple times like when
> >> starting iPXE, when starting GRUB, and again when starting Linux.
> >
> >IIRC the spec says you should try and measure things once.  On top of that
> >it has no wording for DTB,  but for ACPI tables it says they should be 
> >measured prior
> >to any fix-ups.  We pretty much copied the recommendations for ACPI apart
> >from when we measure the data.  For ACPI it says "ACPI flash data prior to
> >any modifications" [0] but since U-Boot allows us to change the loaded DTB we
> >tried to measure the one we end up installing in the config table.
>
> If for ACPI it is sufficient to measure before fixups, doing the same for 
> dtbs should be adequate. This would avoid variable parts like random MAC 
> addresses, boot-hart ID, kaslr seed but should include applied overlays. So 
> just measuring the dtb passed into bootefi or the fallback dtb.

I agree this feature is interesting when the DTB passed was initially
loaded from an external image. Measuring the loaded image(s ?) when
loaded would make more sense but there DTB is can be load from various
commands from generic or custom bootcmd script, commands like
"tftpboot ${fdt_addr_r} dtb/${efi_fdtfile}"  or load_efi_dtb variable
from  include/config_distro_bootcmd.h. We cannot run a generic
measurement a those places.


>
> Why do we measure SMBIOS multiple times?
>
>
> >
> >>
> >> What is the value of measuring the device-tree here when GRUB or
> >> systemd-boot afterwards load a different device-tree or modify the
> >> provided device-tree?
> >
> >If they modify if there's some usage since you, in theory, trust and
> >hopefully verified those binaries and the modifications they are about to
> >perform.
> >If they end up replacing it there's no point in measuring, but that's 
> >exactly why
> >this is under a Kconfig option.  If they load a different DTB then they are 
> >responsible
> >for measuring it?
> >
> >[...]
> >
> >> > +  log_err("ERROR: failed to measure DTB\n");
> >> > +  return ret;
> >> > +  }
> >> > +  }
> >> > +
> >>
> >> %s/using/using the/

acked, thanks.

> >>
> >> > +the passed DTB contains data that change across platform reboots
> >> > +and cannot be used has a predictable measurement. Otherwise
> >>
> >> How should the user know this? Shall we create dependencies to other
> >> Kconfig symbols? e.g.
> >>
> >> depen

[PATCH 2/2] tee: optee: discover services dependent on tee-supplicant

2022-12-07 Thread Etienne Carriere
Makes OP-TEE to enumerate also services depending on tee-supplicant
support in U-Boot. This change allows OP-TEE services like fTPM TA
to be discovered and get a TPM device registered 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 604fd1414f..b21031d7d8 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, , 1, );
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, _size, tee_sess);
+   ret = __enum_services(dev, NULL, _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, _size, tee_sess);
+   ret = __enum_services(dev, *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, _sess);
if (ret)
return ret;
 
-   ret = enum_services(dev, _list, _count, tee_sess);
+   ret = enum_services(dev, _list, _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, _list, _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



[PATCH 1/2] tee: optee: don't fail probe because of optee-rng

2022-12-07 Thread Etienne Carriere
Fixes optee-rng driver bind sequence in optee driver to print a warning
message but not report an error status when a optee-rng service driver
fails to be bound as the optee driver itself is still fully functional.

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 9240277579..604fd1414f 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -834,7 +834,7 @@ static int optee_probe(struct udevice *dev)
 */
ret = device_bind_driver(dev, "optee-rng", "optee-rng", NULL);
if (ret)
-   return ret;
+   dev_warn(dev, "ftpm_tee failed to bind: %d\n", ret);
}
 
return 0;
-- 
2.25.1



[PATCH] tpm2: ftpm: open session with privileged ree login

2022-12-07 Thread Etienne Carriere
Opens the fTPM session with TEE_LOGIN_REE_KERNEL as fTPM may restrict
access to that login when Linux based OS is running as applications are
expected to got through the Linux TPMv2 driver.

Signed-off-by: Etienne Carriere 
---
 drivers/tpm/tpm2_ftpm_tee.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/tpm/tpm2_ftpm_tee.c b/drivers/tpm/tpm2_ftpm_tee.c
index 53e59f42b4..3c4c12983d 100644
--- a/drivers/tpm/tpm2_ftpm_tee.c
+++ b/drivers/tpm/tpm2_ftpm_tee.c
@@ -186,6 +186,7 @@ static int ftpm_tee_probe(struct udevice *dev)
 
/* Open a session with the fTPM TA */
memset(_arg, 0, sizeof(sess_arg));
+   sess_arg.clnt_login = TEE_LOGIN_REE_KERNEL;
tee_optee_ta_uuid_to_octets(sess_arg.uuid, );
 
rc = tee_open_session(context->tee_dev, _arg, 0, NULL);
-- 
2.25.1



[PATCH] efi_loader: Measure the loaded DTB

2022-12-07 Thread Etienne Carriere
Measures the DTB passed to the EFI application upon new boolean config
switch CONFIG_EFI_TCG2_PROTOCOL_MEASURE_DTB. For platforms where the
content of the DTB passed to the OS can change across reboots, there is
not point measuring it hence the config switch to allow platform to not
embed this feature.

Co-developed-by: Ilias Apalodimas 
Signed-off-by: Ilias Apalodimas 
Signed-off-by: Etienne Carriere 
---
 cmd/bootefi.c |  9 +
 include/efi_loader.h  |  2 ++
 include/efi_tcg2.h| 10 ++
 include/tpm-v2.h  |  2 ++
 lib/efi_loader/Kconfig| 12 
 lib/efi_loader/efi_tcg2.c | 36 
 6 files changed, 71 insertions(+)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 2a7d42925d..56e4a1909f 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -315,6 +315,15 @@ efi_status_t efi_install_fdt(void *fdt)
return EFI_LOAD_ERROR;
}
 
+   /* Measure the installed DTB */
+   if (CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL_MEASURE_DTB)) {
+   ret = efi_tcg2_measure_dtb(fdt);
+   if (ret == EFI_SECURITY_VIOLATION) {
+   log_err("ERROR: failed to measure DTB\n");
+   return ret;
+   }
+   }
+
/* Prepare device tree for payload */
ret = copy_fdt();
if (ret) {
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 0899e293e5..7538b6b828 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -530,6 +530,8 @@ efi_status_t 
efi_tcg2_notify_exit_boot_services_failed(void);
 efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj 
*handle);
 /* Measure efi application exit */
 efi_status_t efi_tcg2_measure_efi_app_exit(void);
+/* Measure DTB */
+efi_status_t efi_tcg2_measure_dtb(void *fdt);
 /* Called by bootefi to initialize root node */
 efi_status_t efi_root_node_register(void);
 /* Called by bootefi to initialize runtime */
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index 874306dc11..b1c3abd097 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -233,6 +233,16 @@ struct efi_gpt_data {
gpt_entry partitions[];
 } __packed;
 
+/**
+ * struct tdUEFI_PLATFORM_FIRMWARE_BLOB2
+ * @blob_description_size: Byte size of @data
+ * @data:  Description data
+ */
+struct uefi_platform_firmware_blob2 {
+   u8 blob_description_size;
+   u8 data[];
+} __packed;
+
 struct efi_tcg2_protocol {
efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
   struct 
efi_tcg2_boot_service_capability *capability);
diff --git a/include/tpm-v2.h b/include/tpm-v2.h
index 737e57551d..2df3dad553 100644
--- a/include/tpm-v2.h
+++ b/include/tpm-v2.h
@@ -105,6 +105,8 @@ struct udevice;
"Exit Boot Services Returned with Failure"
 #define EFI_EXIT_BOOT_SERVICES_SUCCEEDED\
"Exit Boot Services Returned with Success"
+#define EFI_DTB_EVENT_STRING \
+   "DTB DATA"
 
 /* TPMS_TAGGED_PROPERTY Structure */
 struct tpms_tagged_property {
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e2b643871b..e490236d14 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -337,6 +337,18 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE
this is going to be allocated twice. One for the eventlog it 
self
and one for the configuration table that is required from the 
spec
 
+config EFI_TCG2_PROTOCOL_MEASURE_DTB
+   bool "Measure DTB with EFI_TCG2_PROTOCOL"
+   depends on EFI_TCG2_PROTOCOL
+   default n
+   help
+ When enabled, the DTB image passed to the booted EFI image is
+ measured using EFI TCG2 protocol. Do not enable this feature if
+ the passed DTB contains data that change across platform reboots
+ and cannot be used has a predictable measurement. Otherwise
+ this feature allows better measurement of the system boot
+ sequence.
+
 config EFI_LOAD_FILE2_INITRD
bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
default y
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index a525ebf75b..51c9d80828 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -2175,6 +2175,42 @@ out1:
return ret;
 }
 
+/**
+ * efi_tcg2_measure_dtb() - measure the dtb used to boot our OS
+ *
+ * @fdt: pointer to the device tree blob
+ *
+ * Return: status code
+ */
+efi_status_t efi_tcg2_measure_dtb(void *fdt)
+{
+   efi_status_t ret;
+   struct uefi_platform_firmware_blob2 *blob;
+   struct udevice *dev;
+   u32 event_size;
+
+   if (!is_tcg2_protocol_installed())
+   return EFI_SUCCESS;
+
+   ret = platform_get_tpm2_device();
+   if (ret != EFI_SUCCESS)
+   return EFI_SECURITY_VIOLATION;
+
+   event_size = s

Re: [PATCH 2/4] fwu: move meta-data management in core

2022-11-07 Thread Etienne Carriere
Hello Jassi,

On Mon, 7 Nov 2022 at 19:29, Jassi Brar  wrote:
>
> On Mon, Nov 7, 2022 at 11:24 AM Etienne Carriere
>  wrote:
> > On Fri, 4 Nov 2022 at 03:43,  wrote:
> > >
> > > +/**
> > > + * 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);
> >
> > Nitpicking: would you be ok to rename this function to fwu_get_mdata().
> > When getting fwu mdata, we obviously expect to get reliable data.
> >
> I originally called it fwu_get_mdata() in my local 1-patch change :)
> But there already is one such function and I had to rename, only to delete 
> that.

Ok, maybe a later commit to rename the function once the old one has
been removed in patch 4/4.

>
> 
> > > +
> > > +static struct fwu_mdata g_mdata = { 0 };
> >
> > Can remove "= { 0 };"
> >
> I knew, but it was supposed to imply that we want the first crc check
> to fail (because we set that to 0 here).

As zero init is implicit, I think maintainers will ask to remove it here.

Maybe add an inline comment above the global variable definition.
/* Crc32 of a zeroes produces a non 0 value */

>
> .
> > > +static inline int mdata_crc_check(struct fwu_mdata *mdata)
> > > +{
> > > +   u32 calc_crc32 = crc32(0, >version, sizeof(*mdata) - 
> > > sizeof(u32));
> >
> > Add an empty line below the above definition.
> >
> OK.
>
> 
> > > +   /* if mdata already read and ready */
> > > +   err = mdata_crc_check(p_mdata, true);
> >
> > 2nd argument to be removed. Ditto for the other occurrences of
> > mdata_crc_check() calls.
> >
> Ouch, I 'cleaned' the patch before submission. Will fix that.
>
> > Note here I would pass straight _mdata as argument rather than
> > p_mdata indirection, for clarity.
> >
> Hmm... I wanted to keep the g_mdata usage clear and minimal.

It looks strange we need to check p_mdata init value to understand
we're accessing the cached mdata.
p_mdata is expected to be the primary part. Perfer keep it for this usage.

br,
etienne

>
> 
> > > +
> > > +   if (!pri_ok) {
> > > +   memcpy(p_mdata, s_mdata, sizeof(struct fwu_mdata));
> > > +   err = fwu_sync_mdata(p_mdata, PRIMARY_PART);
> >
> > Should test return value.
> >
> > > +   }
> > > +
> > > +   if (!sec_ok) {
> > > +   memcpy(s_mdata, p_mdata, sizeof(struct fwu_mdata));
> > > +   err = fwu_sync_mdata(s_mdata, SECONDARY_PART);
> >
> > Ditto
> >
> > > +   }
> > > +
> > > +   /* make sure atleast one copy is good */
> >
> > s/atleast/at least/
> >
> ok
>
> > > +   err = mdata_crc_check(p_mdata, true);
> >
> > This is not needed, it's been already verified unless we want to catch
> > the case !pri_ok && !sec_ok. I think this case should be explicitly
> > handled above with a nice console trace message/
> >
> ok
>
> Thanks.


Re: [PATCH 1/4] fwu: gpt: use cached meta-data partition numbers

2022-11-07 Thread Etienne Carriere
Hello Jassi,

Acked-by: Etienne Carriere 
with the 2 below comments addressed.

On Fri, 4 Nov 2022 at 03:42,  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.
>
> 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..d706e3d4e4 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};

Not needed to initialize to 0.
  "static uint g_mdata_part[2];"   is enough.

> +
> +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 partitons already found */

s/partitons/partitions/

> +   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, ))
> continue;
> uuid_str_to_bin(info.type_guid, part_type_guid.b,
> UUID_STR_FORMAT_GUID);
>
> -   if (!guidcmp(_mdata_guid, _type_guid)) {
> -   if (nparts < 2)
> -   mdata_parts[nparts] = i;
> -   ++nparts;
> -   }
> +   if (!guidcmp(_mdata_guid, _type_guid))
> +   g_mdata_part[nparts++] = i;
> }
>
> if (nparts != 2) {
> @@ -127,26 +129,25 @@ static int fwu_gpt_update_mdata(struct udevice *dev, 
> struct fwu_mdata *mdata)
>  {
> int ret;
> struct blk_desc *desc;
> -   uint mdata_parts[2];
> struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
>
> desc = dev_get_uclass_plat(priv->blk_dev);
>
> -   ret = gpt_get_mdata_partitions(desc, mdata_parts);
> +   ret = gpt_get_mdata_partitions(desc);
> if (ret < 0) {
> log_debug("Error getting the FWU metadata partitions\n");
> return -ENOENT;
> }
>
> /* First write the primary partition */
> -   ret = gpt_read_write_mdata(desc, mdata, MDATA_WRITE, mdata_parts[0]);
> +   ret = gpt_read_write_mdata(desc, mdata, MDATA_WRITE, g_mdata_part[0]);
> if (ret < 0) {
> log_debug("Updating primary FWU metadata partition failed\n");
> return ret;
> }
>
> /* And now the replica */
> -   ret = gpt_read_write_mdata(desc, mdata, MDATA_WRITE, mdata_parts[1]);
> +   ret = gpt_read_write_mdata(desc, mdata, MDATA_WRITE, g_mdata_part[1]);
> if (ret < 0) {
> log_debug("Updating secondary FWU metadata partition 
> failed\n");
> return ret;
> @@ -158,16 +159,14 @@ static int fwu_gpt_update_mdata(struct udevice *dev, 
> struct fwu_mdata *mdata)
>  static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata *mdata)
>  {
> int ret;
> -   uint mdata_parts[2];
> -
> -   ret = gpt_get_mdata_partitions(desc, mdata_parts);
>
> +   ret = gpt_get_mdata_partitions(desc);
> if (ret < 0) {
> log_debug("Error getting the FWU metadata partitions\n");
> return -ENOENT;
> }
>
> -   ret = gpt_read_write_mdata(desc, mdata, MDATA_READ, mdata_parts[0]);
> +   ret = gpt_read_write_mdata(desc, mdata, MDATA_READ, g_mdata_part[0]);
> if (ret < 0) {
> log_debug("Failed to read the FWU metadata from the 
> device\n");
> return -EIO;
> @@ -182,7 +181,7 @@ static int gpt_get_mdata(struct blk_desc *desc, struct 
> fwu_mdata *mdata)
>  * Try to read the replica.
>  */
> memset(mdata, '\0', sizeof(struct fwu_mdata));
> -   ret = gpt_read_write_mdata(desc, mdata, MDATA_READ, mdata_parts[1]);
> +   ret = gpt_read_write_mdata(desc, mdata, MD

Re: [PATCH 2/4] fwu: move meta-data management in core

2022-11-07 Thread Etienne Carriere
Hello Jassi,

On Fri, 4 Nov 2022 at 03:43,  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| 136 ++-
>  3 files changed, 207 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c 
> b/drivers/fwu-mdata/fwu-mdata-uclass.c
> index b477e9603f..ded9902971 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);

Nitpicking: would you be ok to rename this function to fwu_get_mdata().
When getting fwu mdata, we obviously expect to get reliable data.

> +
>  /**
>   * 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..3d51b91ed5 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 };

Can remove "= { 0 };"

> +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,134 @@ 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: 

Re: [PATCH 3/4] fwu: gpt: implement read_mdata and write_mdata callbacks

2022-11-07 Thread Etienne Carriere
On Fri, 4 Nov 2022 at 03:43,  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 | 36 
>  1 file changed, 36 insertions(+)
>
> diff --git a/drivers/fwu-mdata/gpt_blk.c b/drivers/fwu-mdata/gpt_blk.c
> index d706e3d4e4..7fda041302 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;

Not returning ret value?

> +   }
> +
> +   return gpt_read_write_mdata(desc, mdata, MDATA_READ,
> +   primary ? g_mdata_part[0] : 
> g_mdata_part[1]);

Fix indentation.


> +}
> +
> +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]);

Dito

Br,
etienne

> +}
> +
>  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.25.1
>


Re: [PATCH 4/4] fwu: meta-data: switch to management by common code

2022-11-07 Thread Etienne Carriere
Hello Jassi,

FYI, I've successfully tested this series on stm32mp1 for FWU, once
the few typos fixed to build it them.


On Fri, 4 Nov 2022 at 03:43,  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(-)
>
> 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) {
> -   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, );
> +   res = fwu_get_verified_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 ded9902971..8190113843 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)
> -{
> -   const struct fwu_mdata_ops *ops = device_get_ops(dev);
> -
> -   if (!ops->write_mdata_partition) {
> -   log_debug("write_mdata_partition() method not defined\n");
> -   return -ENOSYS;
> -   }
> -
> -   return ops->write_mdata_partition(dev, mdata, part_num);
> -}
> -
> -/**
> - * fwu_mdata_check() - Check if the FWU metadata is valid
> - * 

Re: [PATCH v15 14/15] mkeficapsule: Add support for setting OEM flags in capsule header

2022-10-25 Thread Etienne Carriere
Hello Sughosh,


For the v15 series: Tested-by: Etienne Carriere 

Best regards,
Etienne


On Fri, 21 Oct 2022 at 14:47, Sughosh Ganu  wrote:
>
> Add support for setting OEM flags in the capsule header. As per the
> UEFI specification, bits 0-15 of the flags member of the capsule
> header can be defined per capsule GUID.
>
> The oemflags will be used for the FWU Multi Bank update feature, as
> specified by the Dependable Boot specification[1]. Bit
> 15 of the flags member will be used to determine if the
> acceptance/rejection of the updated images is to be done by the
> firmware or an external component like the OS.
>
> [1] - 
> https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
>
> Signed-off-by: Sughosh Ganu 
> Reviewed-by: Ilias Apalodimas 
> Acked-by: Etienne Carriere 
> ---
> Changes since V14:
> * Add a range check for the oemflags passed as suggested by Etienne
>
>  doc/mkeficapsule.1   |  4 
>  tools/mkeficapsule.c | 22 +++---
>  2 files changed, 23 insertions(+), 3 deletions(-)
>
> diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> index 77ca061efd..6fb2dd0810 100644
> --- a/doc/mkeficapsule.1
> +++ b/doc/mkeficapsule.1
> @@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule
>  .BI "-R\fR,\fB --fw-revert "
>  Generate a firmware revert empty capsule
>
> +.TP
> +.BI "-o\fR,\fB --capoemflag "
> +Capsule OEM flag, value between 0x to 0x
> +
>  .TP
>  .BR -h ", " --help
>  Print a help message
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index 25bfb39e5b..b71537beee 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
>  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
>  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>
> -static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
> +static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
>
>  enum {
> CAPSULE_NORMAL_BLOB = 0,
> @@ -47,6 +47,7 @@ static struct option options[] = {
> {"dump-sig", no_argument, NULL, 'd'},
> {"fw-accept", no_argument, NULL, 'A'},
> {"fw-revert", no_argument, NULL, 'R'},
> +   {"capoemflag", required_argument, NULL, 'o'},
> {"help", no_argument, NULL, 'h'},
> {NULL, 0, NULL, 0},
>  };
> @@ -65,6 +66,7 @@ static void print_usage(void)
> "\t-d, --dump_sig  dump signature (*.p7)\n"
> "\t-A, --fw-accept  firmware accept capsule, requires GUID, 
> no image blob\n"
> "\t-R, --fw-revert  firmware revert capsule, takes no GUID, 
> no image blob\n"
> +   "\t-o, --capoemflag Capsule OEM Flag, an integer between 
> 0x and 0x\n"
> "\t-h, --help  print a help message\n",
> tool_name);
>  }
> @@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx)
>   * @mcount:Monotonic count in authentication information
>   * @private_file:  Path to a private key file
>   * @cert_file: Path to a certificate file
> + * @oemflags:  Capsule OEM Flags, bits 0-15
>   *
>   * This function actually does the job of creating an uefi capsule file.
>   * All the arguments must be supplied.
> @@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx)
>   */
>  static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> unsigned long index, unsigned long instance,
> -   uint64_t mcount, char *privkey_file, char *cert_file)
> +   uint64_t mcount, char *privkey_file, char *cert_file,
> +   uint16_t oemflags)
>  {
> struct efi_capsule_header header;
> struct efi_firmware_management_capsule_header capsule;
> @@ -464,6 +468,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t 
> *guid,
> header.header_size = sizeof(header);
> /* TODO: The current implementation ignores flags */
> header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +   if (oemflags)
> +   header.flags |= oemflags;
> header.capsule_image_size = sizeof(header)
> + sizeof(capsule) + sizeof(uint64_t)
> + sizeof(image)
> @@ -635,6 +641,7 @@ int main(int argc, char **argv)
> unsigned char uuid_buf[16];
> unsigned long index, instance;
> 

Re: [PATCH v5 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface

2022-10-25 Thread Etienne Carriere
Hello Kojima-san,

On Tue, 25 Oct 2022 at 05:17, Masahisa Kojima
 wrote:
>
> This commit adds the menu-driven UEFI Secure Boot Key
> enrollment interface. User can enroll the PK, KEK, db
> and dbx by selecting EFI Signature Lists file.
> After the PK is enrolled, UEFI Secure Boot is enabled and
> EFI Signature Lists file must be signed by KEK or PK.
>
> Signed-off-by: Masahisa Kojima 
> ---
> No change since v4
>
> Changes in v4:
> - add CONFIG_EFI_MM_COMM_TEE dependency
> - fix error handling
>
> Changes in v3:
> - fix error handling
>
> Changes in v2:
> - allow to enroll .esl file
> - fix typos
> - add function comments
>
>  cmd/Makefile  |   5 +
>  cmd/eficonfig.c   |   3 +
>  cmd/eficonfig_sbkey.c | 357 ++
>  include/efi_config.h  |   5 +
>  4 files changed, 370 insertions(+)
>  create mode 100644 cmd/eficonfig_sbkey.c
>
> diff --git a/cmd/Makefile b/cmd/Makefile
> index c95e09d058..e43ef22e98 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -66,6 +66,11 @@ obj-$(CONFIG_CMD_EEPROM) += eeprom.o
>  obj-$(CONFIG_EFI) += efi.o
>  obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
>  obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o
> +ifdef CONFIG_CMD_EFICONFIG
> +ifdef CONFIG_EFI_MM_COMM_TEE
> +obj-$(CONFIG_EFI_SECURE_BOOT) += eficonfig_sbkey.o
> +endif
> +endif
>  obj-$(CONFIG_CMD_ELF) += elf.o
>  obj-$(CONFIG_CMD_EROFS) += erofs.o
>  obj-$(CONFIG_HUSH_PARSER) += exit.o
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index c765b795d0..0b643a046c 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -2447,6 +2447,9 @@ static const struct eficonfig_item 
> maintenance_menu_items[] = {
> {"Edit Boot Option", eficonfig_process_edit_boot_option},
> {"Change Boot Order", eficonfig_process_change_boot_order},
> {"Delete Boot Option", eficonfig_process_delete_boot_option},
> +#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && 
> CONFIG_IS_ENABLED(EFI_MM_COMM_TEE))
> +   {"Secure Boot Configuration", eficonfig_process_secure_boot_config},
> +#endif
> {"Quit", eficonfig_process_quit},
>  };
>
> diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
> new file mode 100644
> index 00..32a39eb7ba
> --- /dev/null
> +++ b/cmd/eficonfig_sbkey.c
> @@ -0,0 +1,357 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + *  Menu-driven UEFI Secure Boot Key Maintenance
> + *
> + *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +enum efi_sbkey_signature_type {
> +   SIG_TYPE_X509 = 0,
> +   SIG_TYPE_HASH,
> +   SIG_TYPE_CRL,
> +   SIG_TYPE_RSA2048,
> +};
> +
> +struct eficonfig_sigtype_to_str {
> +   efi_guid_t sig_type;
> +   char *str;
> +   enum efi_sbkey_signature_type type;
> +};
> +
> +static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
> +   {EFI_CERT_X509_GUID,"X509", 
> SIG_TYPE_X509},
> +   {EFI_CERT_SHA256_GUID,  "SHA256",   
> SIG_TYPE_HASH},
> +   {EFI_CERT_X509_SHA256_GUID, "X509_SHA256 CRL",  SIG_TYPE_CRL},
> +   {EFI_CERT_X509_SHA384_GUID, "X509_SHA384 CRL",  SIG_TYPE_CRL},
> +   {EFI_CERT_X509_SHA512_GUID, "X509_SHA512 CRL",  SIG_TYPE_CRL},
> +   /* U-Boot does not support the following signature types */
> +/* {EFI_CERT_RSA2048_GUID, "RSA2048",  
> SIG_TYPE_RSA2048}, */
> +/* {EFI_CERT_RSA2048_SHA256_GUID,  "RSA2048_SHA256",   
> SIG_TYPE_RSA2048}, */
> +/* {EFI_CERT_SHA1_GUID,"SHA1", 
> SIG_TYPE_HASH}, */
> +/* {EFI_CERT_RSA2048_SHA_GUID, "RSA2048_SHA",  
> SIG_TYPE_RSA2048 }, */
> +/* {EFI_CERT_SHA224_GUID,  "SHA224",   
> SIG_TYPE_HASH}, */
> +/* {EFI_CERT_SHA384_GUID,  "SHA384",   
> SIG_TYPE_HASH}, */
> +/* {EFI_CERT_SHA512_GUID,  "SHA512",   
> SIG_TYPE_HASH}, */
> +};
> +
> +/**
> + * is_secureboot_enabled() - check UEFI Secure Boot is enabled
> + *
> + * Return: true when UEFI Secure Boot is enabled, false otherwise
> + */
> +static bool is_secureboot_enabled(void)
> +{
> +   efi_status_t ret;
> +   u8 secure_boot;
> +   efi_uintn_t size;
> +
> +   size = sizeof(secure_boot);
> +   ret = efi_get_variable_int(u"SecureBoot", _global_variable_guid,
> +  NULL, , _boot, NULL);
> +
> +   return secure_boot == 1;

This should test 'ret{ against EFI_SUCCESS and EFI_NOT_FOUND.
I think the logic should be:
  if (ret == EFI_SUCCESS) { return secure_boot == 1; }
  else if (ret == EFI_NOT_FOUND) { return false; }
  else { /* enforce secure bool policy on error */ return true; }

That said, there is the exported efi_secure_boot_enabled() that should
be reliable, i think.


> +}
> +
> +/**
> + * create_time_based_payload() - 

Re: [PATCH v14 15/15] FWU: doc: Add documentation for the FWU feature

2022-10-20 Thread Etienne Carriere
Hi Sughosh,

For info I successfully tested your v14 series on my boards.
(note i did not test case with a power failure in between mdata
partition updates, discussed in patch v14 02/15).
I'll run another tests round on next v15 to post my Tested-by tag.

Br,
Etienne

On Tue, 18 Oct 2022 at 13:45, 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 V13: None
>
>  doc/develop/uefi/fwu_updates.rst | 184 +++
>  doc/develop/uefi/index.rst   |   1 +
>  doc/develop/uefi/uefi.rst|  12 ++
>  3 files changed, 197 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..068616ce83
> --- /dev/null
> +++ b/doc/develop/uefi/fwu_updates.rst
> @@ -0,0 +1,184 @@
> +.. 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_FWU_MDATA=y
> +CONFIG_FWU_MDATA_GPT_BLK=y
> +CONFIG_FWU_NUM_BANKS=
> +CONFIG_FWU_NUM_IMAGES_PER_BANK=
> +
> +in the .config file
> +
> +By enabling the CONFIG_CMD_FWU_METADATA config option, the
> +fwu_mdata_read command can be used to check the current state of the
> +FWU metadata structure.
> +
> +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. These
> +partitions need to be created at the time of the platform's
> +provisioning.
> +
> +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. Each 

Re: [PATCH v14 14/15] mkeficapsule: Add support for setting OEM flags in capsule header

2022-10-20 Thread Etienne Carriere
On Thu, 20 Oct 2022 at 16:11, Sughosh Ganu  wrote:
>
> On Thu, 20 Oct 2022 at 19:25, Etienne Carriere
>  wrote:
> >
> > On Tue, 18 Oct 2022 at 13:44, Sughosh Ganu  wrote:
> > >
> > > Add support for setting OEM flags in the capsule header. As per the
> > > UEFI specification, bits 0-15 of the flags member of the capsule
> > > header can be defined per capsule GUID.
> > >
> > > The oemflags will be used for the FWU Multi Bank update feature, as
> > > specified by the Dependable Boot specification[1]. Bit
> > > 15 of the flags member will be used to determine if the
> > > acceptance/rejection of the updated images is to be done by the
> > > firmware or an external component like the OS.
> > >
> > > [1] - 
> > > https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
> > >
> > > Signed-off-by: Sughosh Ganu 
> > > Reviewed-by: Ilias Apalodimas 
> > > ---
> > > Changes since V13: None
> > >
> > >  doc/mkeficapsule.1   |  4 
> > >  tools/mkeficapsule.c | 17 ++---
> > >  2 files changed, 18 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> > > index 77ca061efd..6fb2dd0810 100644
> > > --- a/doc/mkeficapsule.1
> > > +++ b/doc/mkeficapsule.1
> > > @@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule
> > >  .BI "-R\fR,\fB --fw-revert "
> > >  Generate a firmware revert empty capsule
> > >
> > > +.TP
> > > +.BI "-o\fR,\fB --capoemflag "
> > > +Capsule OEM flag, value between 0x to 0x
> > > +
> > >  .TP
> > >  .BR -h ", " --help
> > >  Print a help message
> > > diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> > > index 25bfb39e5b..b24f873b48 100644
> > > --- a/tools/mkeficapsule.c
> > > +++ b/tools/mkeficapsule.c
> > > @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
> > >  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
> > >  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> > >
> > > -static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
> > > +static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
> > >
> > >  enum {
> > > CAPSULE_NORMAL_BLOB = 0,
> > > @@ -47,6 +47,7 @@ static struct option options[] = {
> > > {"dump-sig", no_argument, NULL, 'd'},
> > > {"fw-accept", no_argument, NULL, 'A'},
> > > {"fw-revert", no_argument, NULL, 'R'},
> > > +   {"capoemflag", required_argument, NULL, 'o'},
> > > {"help", no_argument, NULL, 'h'},
> > > {NULL, 0, NULL, 0},
> > >  };
> > > @@ -65,6 +66,7 @@ static void print_usage(void)
> > > "\t-d, --dump_sig  dump signature (*.p7)\n"
> > > "\t-A, --fw-accept  firmware accept capsule, requires 
> > > GUID, no image blob\n"
> > > "\t-R, --fw-revert  firmware revert capsule, takes no 
> > > GUID, no image blob\n"
> > > +   "\t-o, --capoemflag Capsule OEM Flag, an integer between 
> > > 0x and 0x\n"
> > > "\t-h, --help  print a help message\n",
> > > tool_name);
> > >  }
> > > @@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx)
> > >   * @mcount:Monotonic count in authentication information
> > >   * @private_file:  Path to a private key file
> > >   * @cert_file: Path to a certificate file
> > > + * @oemflags:  Capsule OEM Flags, bits 0-15
> > >   *
> > >   * This function actually does the job of creating an uefi capsule file.
> > >   * All the arguments must be supplied.
> > > @@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx)
> > >   */
> > >  static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > unsigned long index, unsigned long instance,
> > > -   uint64_t mcount, char *privkey_file, char 
> > > *cert_file)
> > > +   uint64_t mcount, char *privkey_file, char 
> > > *cert_file,
> > > +   uint16_t oemflags)
&g

Re: [PATCH v14 08/15] event: Add an event for main_loop

2022-10-20 Thread Etienne Carriere
On Tue, 18 Oct 2022 at 13:44, Sughosh Ganu  wrote:
>
> Add an event type EVT_MAIN_LOOP that can be used for registering
> events that need to be run after the platform has been initialised and
> before the main_loop function is called.
>
> Signed-off-by: Sughosh Ganu 
> Reviewed-by: Simon Glass 
> Reviewed-by: Ilias Apalodimas 
> ---
> Changes since V13: None
>

Acked-by: Etienne Carriere 


>  common/board_r.c | 3 +++
>  common/event.c   | 3 +++
>  include/event.h  | 3 +++
>  3 files changed, 9 insertions(+)
>
> diff --git a/common/board_r.c b/common/board_r.c
> index 92ca2066ee..62e5e783f1 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -579,6 +579,9 @@ static int run_main_loop(void)
>  #ifdef CONFIG_SANDBOX
> sandbox_main_loop_init();
>  #endif
> +
> +   event_notify_null(EVT_MAIN_LOOP);
> +
> /* main_loop() can return to retry autoboot, if so just run it again 
> */
> for (;;)
> main_loop();
> diff --git a/common/event.c b/common/event.c
> index 3e34550978..231b9e6ffd 100644
> --- a/common/event.c
> +++ b/common/event.c
> @@ -38,6 +38,9 @@ const char *const type_name[] = {
>
> /* fdt hooks */
> "ft_fixup",
> +
> +   /* main loop events */
> +   "main_loop",
>  };
>
>  _Static_assert(ARRAY_SIZE(type_name) == EVT_COUNT, "event type_name size");
> diff --git a/include/event.h b/include/event.h
> index 3e6dcbc3dd..e4580b6835 100644
> --- a/include/event.h
> +++ b/include/event.h
> @@ -34,6 +34,9 @@ enum event_t {
> /* Device tree fixups before booting */
> EVT_FT_FIXUP,
>
> +   /* To be called once, before calling main_loop() */
> +   EVT_MAIN_LOOP,
> +
> EVT_COUNT
>  };
>
> --
> 2.34.1
>


Re: [PATCH v14 07/15] FWU: STM32MP1: Add support to read boot index from backup register

2022-10-20 Thread Etienne Carriere
On Tue, 18 Oct 2022 at 13:44, 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 V13: None
>

Acked-by: Etienne Carriere 

>  arch/arm/mach-stm32mp/include/mach/stm32.h |  5 +
>  board/st/stm32mp1/stm32mp1.c   | 21 +
>  include/fwu.h  | 12 
>  3 files changed, 38 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 98e96d9e0b..47b3d1bf4c 100644
> --- a/board/st/stm32mp1/stm32mp1.c
> +++ b/board/st/stm32mp1/stm32mp1.c
> @@ -957,3 +957,24 @@ 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)
> +{
> +   *boot_idx = (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 b80ae1b35c..7d38cb5856 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -333,4 +333,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 v14 13/15] mkeficapsule: Add support for generating empty capsules

2022-10-20 Thread Etienne Carriere
On Tue, 18 Oct 2022 at 13:44, Sughosh Ganu  wrote:
>
> The Dependable Boot specification[1] describes the structure of the
> firmware accept and revert capsules. These are empty capsules which
> are used for signalling the acceptance or rejection of the updated
> firmware by the OS. Add support for generating these empty capsules.
>
> [1] - 
> https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
>
> Signed-off-by: Sughosh Ganu 
> Acked-by: Ilias Apalodimas 
> ---
> Changes since V13: None
>
>  doc/mkeficapsule.1   | 29 +
>  tools/eficapsule.h   |  8 
>  tools/mkeficapsule.c | 96 
>  3 files changed, 119 insertions(+), 14 deletions(-)
>

Acked-by: Etienne Carriere 


> diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> index 09bdc24295..77ca061efd 100644
> --- a/doc/mkeficapsule.1
> +++ b/doc/mkeficapsule.1
> @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot
>
>  .SH SYNOPSIS
>  .B mkeficapsule
> -.RI [ options "] " image-blob " " capsule-file
> +.RI [ options ] " " [ image-blob ] " " capsule-file
>
>  .SH "DESCRIPTION"
>  .B mkeficapsule
> @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given 
> private key.
>  In this case, the update will be authenticated by verifying the signature
>  before applying.
>
> +Additionally, an empty capsule file can be generated for acceptance or
> +rejection of firmware images by a governing component like an Operating
> +System. The empty capsules do not require an image-blob input file.
> +
> +
>  .B mkeficapsule
> -takes any type of image files, including:
> +takes any type of image files when generating non empty capsules, including:
>  .TP
>  .I raw image
>  format is a single binary blob of any type of firmware.
> @@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file.
>  This type of image file can be generated by
>  .BR mkimage .
>
> -.PP
> -If you want to use other types than above two, you should explicitly
> -specify a guid for the FMP driver.
> -
>  .SH "OPTIONS"
> +
>  .TP
>  .BI "-g\fR,\fB --guid " guid-string
>  Specify guid for image blob type. The format is:
>  ----
>
>  The first three elements are in little endian, while the rest
> -is in big endian.
> +is in big endian. The option must be specified for all non empty and
> +image acceptance capsules
>
>  .TP
>  .BI "-i\fR,\fB --index " index
> @@ -57,6 +60,18 @@ Specify an image index
>  .BI "-I\fR,\fB --instance " instance
>  Specify a hardware instance
>
> +.PP
> +For generation of firmware accept empty capsule
> +.BR --guid
> +is mandatory
> +.TP
> +.BI "-A\fR,\fB --fw-accept "
> +Generate a firmware acceptance empty capsule
> +
> +.TP
> +.BI "-R\fR,\fB --fw-revert "
> +Generate a firmware revert empty capsule
> +
>  .TP
>  .BR -h ", " --help
>  Print a help message
> diff --git a/tools/eficapsule.h b/tools/eficapsule.h
> index d63b831443..072a4b5598 100644
> --- a/tools/eficapsule.h
> +++ b/tools/eficapsule.h
> @@ -41,6 +41,14 @@ typedef struct {
> EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \
>  0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7)
>
> +#define FW_ACCEPT_OS_GUID \
> +   EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> +0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
> +
> +#define FW_REVERT_OS_GUID \
> +   EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> +0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> +
>  /* flags */
>  #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET  0x0001
>
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index 5f74d23b9e..25bfb39e5b 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,7 +29,13 @@ static const char *tool_name = "mkeficapsule";
>  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
>  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>
> -static const char *opts_short = "g:i:I:v:p:c:m:dh";
> +static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
> +
> +enum {
> +   CAPSULE_NORMAL_BLOB = 0,
> +   CAPSULE_ACCEPT,
> +   CAPSULE_REVERT,
> +} capsule_type;
>
>  static struct option options[] = {
> {"guid", required_argument, NULL, 'g'},
> @@ -39,6 +45,8 @@ static struct option options[] = {
> {"certificate", required_argument, NULL, 'c'},
> {"monotonic-cou

Re: [PATCH v14 15/15] FWU: doc: Add documentation for the FWU feature

2022-10-20 Thread Etienne Carriere
; > +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. Each GPT partition entry in the GPT header has two GUIDs::
> > +
> > +* PartitionTypeGUID
> > +* UniquePartitionGUID
> > +
> > +The PartitionTypeGUID value should correspond to the
> > +``image_type_uuid`` field of the FWU metadata. This field is used to
> > +identify a given type of updatable firmware image, e.g. U-Boot,
> > +OP-TEE, FIP etc. This GUID should also be used for specifying the
> > +`--guid` parameter when generating the capsule.
> > +
> > +The UniquePartitionGUID value should correspond to the ``image_uuid``
> > +field in the FWU metadata. This GUID is used to identify images of a
> > +given image type in different banks.
> > +
> > +The FWU specification defines the GUID value to be used for the
> > +metadata partitions. This would be the PartitionTypeGUID for the
> > +metadata partitions. Similarly, the UEFI specification defines the ESP
> > +GUID to be be used.
> > +
> > +When generating the metadata, the ``image_type_uuid`` and the
> > +``image_uuid`` values should match the *PartitionTypeGUID* and the
> > +*UniquePartitionGUID* values respectively.
> > +
> > +Performing the Update
> > +-
> > +
> > +Once the storage media has been partitioned and populated with the
> > +metadata partitions, the UEFI capsule-on-disk update functionality can
> > +be used for performing the update. Refer to the section
> > +:ref:`uefi_capsule_update_ref` for details on how the update can be
> > +invoked.
> > +
> > +On a successful update, the FWU metadata gets updated to reflect the
> > +bank from which the platform would be booting on subsequent boot.
> > +
> > +Based on the value of bit15 of the Flags member of the capsule header,
> > +the updated images would either be accepted by the U-Boot's UEFI
> > +implementation, or by the Operating System. If the Operating System is
> > +accepting the firmware images, it does so by generating an empty
> > +*accept* capsule. The Operating System can also reject the updated
> > +firmware by generating a *revert* capsule. The empty capsule can be
> > +applied by using the exact same procedure used for performing the
> > +capsule-on-disk update.
> > +
> > +The task of accepting the different firmware images, post an update
> > +may be done by multiple, separate components in the Operating
> > +System. To help identify the firmware image that is being accepted,
> > +the accept capsule passes the image GUID of the firmware image being
> > +accepted. The relevant code in U-Boot then sets the Accept bit of the
> > +corresponding firmware image for which the accept capsule was
> > +found. Only when all the firmware components in a bank have been
> > +accepted does the platform transition from trial state to regular
> > +state.
> > +
> > +The revert capsule on the other hand does not pass any image GUID,
> > +since reverting any image of the bank has the same result of the
> > +platform booting from the other bank on subsequent boot.
> > +
> > +In the scenario that bit15 of the Flags member of the capsule header
> > +has not been set, the images being updated are accepted by the
> > +U-Boot's UEFI firmware implementation by default, on successful
> > +updation of the image.

s/updation/update/

For this fixed, Acked-by: Etienne Carriere 

br,
etienne

> > +
> > +Generating an empty capsule
> > +---
> > +
> > +The empty capsule can be generated using the mkeficapsule utility. To
> > +build the tool, enable::
> > +
> > +CONFIG_TOOLS_MKEFICAPSULE=y
> > +
> > +Run the following commands to generate the accept/revert capsules::
> > +
> > +.. code-block:: bash
> > +
> > +$ ./tools/mkeficapsule \
> > +  [--fw-accept --guid ] | \
> > +  [--fw-revert] \
> > +  
> > +
> > +Some examples of using the mkeficapsule tool for generation of the
> > +empty capsule woul

Re: [PATCH v14 14/15] mkeficapsule: Add support for setting OEM flags in capsule header

2022-10-20 Thread Etienne Carriere
On Tue, 18 Oct 2022 at 13:44, Sughosh Ganu  wrote:
>
> Add support for setting OEM flags in the capsule header. As per the
> UEFI specification, bits 0-15 of the flags member of the capsule
> header can be defined per capsule GUID.
>
> The oemflags will be used for the FWU Multi Bank update feature, as
> specified by the Dependable Boot specification[1]. Bit
> 15 of the flags member will be used to determine if the
> acceptance/rejection of the updated images is to be done by the
> firmware or an external component like the OS.
>
> [1] - 
> https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
>
> Signed-off-by: Sughosh Ganu 
> Reviewed-by: Ilias Apalodimas 
> ---
> Changes since V13: None
>
>  doc/mkeficapsule.1   |  4 
>  tools/mkeficapsule.c | 17 ++---
>  2 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> index 77ca061efd..6fb2dd0810 100644
> --- a/doc/mkeficapsule.1
> +++ b/doc/mkeficapsule.1
> @@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule
>  .BI "-R\fR,\fB --fw-revert "
>  Generate a firmware revert empty capsule
>
> +.TP
> +.BI "-o\fR,\fB --capoemflag "
> +Capsule OEM flag, value between 0x to 0x
> +
>  .TP
>  .BR -h ", " --help
>  Print a help message
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index 25bfb39e5b..b24f873b48 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
>  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
>  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>
> -static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
> +static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
>
>  enum {
> CAPSULE_NORMAL_BLOB = 0,
> @@ -47,6 +47,7 @@ static struct option options[] = {
> {"dump-sig", no_argument, NULL, 'd'},
> {"fw-accept", no_argument, NULL, 'A'},
> {"fw-revert", no_argument, NULL, 'R'},
> +   {"capoemflag", required_argument, NULL, 'o'},
> {"help", no_argument, NULL, 'h'},
> {NULL, 0, NULL, 0},
>  };
> @@ -65,6 +66,7 @@ static void print_usage(void)
> "\t-d, --dump_sig  dump signature (*.p7)\n"
> "\t-A, --fw-accept  firmware accept capsule, requires GUID, 
> no image blob\n"
> "\t-R, --fw-revert  firmware revert capsule, takes no GUID, 
> no image blob\n"
> +   "\t-o, --capoemflag Capsule OEM Flag, an integer between 
> 0x and 0x\n"
> "\t-h, --help  print a help message\n",
> tool_name);
>  }
> @@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx)
>   * @mcount:Monotonic count in authentication information
>   * @private_file:  Path to a private key file
>   * @cert_file: Path to a certificate file
> + * @oemflags:  Capsule OEM Flags, bits 0-15
>   *
>   * This function actually does the job of creating an uefi capsule file.
>   * All the arguments must be supplied.
> @@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx)
>   */
>  static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> unsigned long index, unsigned long instance,
> -   uint64_t mcount, char *privkey_file, char *cert_file)
> +   uint64_t mcount, char *privkey_file, char *cert_file,
> +   uint16_t oemflags)
>  {
> struct efi_capsule_header header;
> struct efi_firmware_management_capsule_header capsule;
> @@ -464,6 +468,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t 
> *guid,
> header.header_size = sizeof(header);
> /* TODO: The current implementation ignores flags */
> header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
> +   if (oemflags)
> +   header.flags |= oemflags;
> header.capsule_image_size = sizeof(header)
> + sizeof(capsule) + sizeof(uint64_t)
> + sizeof(image)
> @@ -635,6 +641,7 @@ int main(int argc, char **argv)
> unsigned char uuid_buf[16];
> unsigned long index, instance;
> uint64_t mcount;
> +   uint16_t oemflags;
> char *privkey_file, *cert_file;
> int c, idx;
>
> @@ -646,6 +653,7 @@ int main(int argc, char **argv)
> cert_file = NULL;
> dump_sig = 0;
> capsule_type = CAPSULE_NORMAL_BLOB;
> +   oemflags = 0;
> for (;;) {
> c = getopt_long(argc, argv, opts_short, options, );
> if (c == -1)
> @@ -709,6 +717,9 @@ int main(int argc, char **argv)
> }
> capsule_type = CAPSULE_REVERT;
> break;
> +   case 'o':
> +   oemflags = strtoul(optarg, 

Re: [PATCH v14 02/15] FWU: Add FWU metadata structure and driver for accessing metadata

2022-10-19 Thread Etienne Carriere
Hi Sughosh, Ilias,

On Wed, 19 Oct 2022 at 21:56, Ilias Apalodimas
 wrote:
>
> Hi Sughosh
>
>
> [...]
>
> > + *
> > + * 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_check_mdata_validity(void)
> > +{
> > + int ret;
> > + struct udevice *dev;
> > + struct fwu_mdata pri_mdata;
> > + struct fwu_mdata secondary_mdata;
> > + uint mdata_parts[2];
> > + uint valid_partitions, invalid_partitions;
> > +
> > + ret = fwu_get_dev_mdata(, NULL);
> > + if (ret)
> > + return ret;
> > +
> > + /*
> > +  * Check if the platform has defined its own
> > +  * function to check the metadata partitions'
> > +  * validity. If so, that takes precedence.
> > +  */
> > + ret = fwu_mdata_check(dev);
>
> Isn't this a bit dangerous?  Let's say a device defines it's own check
> function but for some reason returns -ENOSYS.  I am wondering if we should
> just return 0 if the platform defined functions aren't defined.
>
> > + if (!ret || ret != -ENOSYS)
> > + return ret;
> > +
> > + /*
> > +  * Two FWU metadata partitions are expected.
> > +  * If we don't have two, user needs to create
> > +  * them first
> > +  */
> > + valid_partitions = 0;
> > + ret = fwu_get_mdata_part_num(dev, mdata_parts);
> > + if (ret < 0) {
> > + log_debug("Error getting the FWU metadata partitions\n");
> > + return -ENOENT;
> > + }
> > +
> > + ret = fwu_read_mdata_partition(dev, _mdata, mdata_parts[0]);
> > + if (!ret) {
> > + ret = fwu_verify_mdata(_mdata, 1);
> > + if (!ret)
> > + valid_partitions |= PRIMARY_PART;
> > + }
> > +
> > + ret = fwu_read_mdata_partition(dev, _mdata, mdata_parts[1]);
> > + if (!ret) {
> > + ret = fwu_verify_mdata(_mdata, 0);
> > + if (!ret)
> > + valid_partitions |= SECONDARY_PART;
> > + }
> > +
> > + if (valid_partitions == (PRIMARY_PART | SECONDARY_PART)) {
> > + /*
> > +  * Before returning, check that both the
> > +  * FWU metadata copies are the same. If not,
> > +  * the FWU metadata copies need to be
> > +  * re-populated.
> > +  */
> > + if (!memcmp(_mdata, _mdata,
> > + sizeof(struct fwu_mdata))) {
> > + ret = 0;
> > + } else {
> > + log_info("Both FWU metadata copies are valid but do 
> > not match. Please check!\n");
>
> Check what ? Just remove that part please

Discussing with Sughosh, here we could update secondary partition with
primary content.
This would prevent us from bricking an update if a power failure
happens before backup (secondary) mdata image is updated.

The code that updates mdata content (patch fwu_gpt_update_mdata() in
patch 03/15) first updates primary partition, then the secondary. It
should be the mandated policy:
1/ ensure secondary content primary content, 2/ update primary 3/
update secondary.
So here, we can safely use the primary if content looks consistent. If
secondary differs from primary, it means the former was not
successfully updated after primary was loaded with new content.

br,
etienne

>
> > + ret = -1;
> > + }
> > + goto out;
> > + }
> > +
> > + if (!(valid_partitions & BOTH_PARTS)) {
> > + ret = -1;
>
> In general we should try to avoid returning -1 etc.  Is there an errno that
> would make sense?
>
> > + goto out;
> > + }
> > +
> > + invalid_partitions = valid_partitions ^ BOTH_PARTS;
> > + ret = fwu_write_mdata_partition(dev,
> > + (invalid_partitions == PRIMARY_PART) ?
> > + _mdata : _mdata,
> > + (invalid_partitions == PRIMARY_PART) ?
> > + mdata_parts[0] : mdata_parts[1]);
> > +
> > + if (ret < 0)
> > + log_info("Restoring %s FWU metadata partition failed\n",
> > +   (invalid_partitions == PRIMARY_PART) ?
> > +   "primary" : "secondary");
> > +
> > +out:
> > + return ret;
> > +}
> > +
> > +/**
> > + * fwu_get_active_index() - Get active_index from the FWU metadata
> > + * @active_idx: active_index value to be read
> > + *
> > + * Read the active_index field from the FWU metadata and place it in
> > + * the variable pointed to be the function argument.
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_get_active_index(uint *active_idx)
> > +{
> > + int ret;
> > + struct udevice *dev;
> > + struct fwu_mdata mdata = 

Re: [PATCH v13 04/15] stm32mp1: dk2: Add a node for the FWU metadata device

2022-10-10 Thread Etienne Carriere
Hello Sughosh,

By the way, could you also add in your series a patch for
stm32mp157c-ev1-u-boot.dtsi with the same node (with sdmmc1 phandle).
This syncs the supports for these to boards.

Best regards,
Etienne

On Thu, 6 Oct 2022 at 11:07, 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 
> Acked-by: Etienne Carriere 
> ---
> Changes since V12: None
>
>  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 = <>;
> +   };
> +};
> --
> 2.34.1
>


Re: [PATCH v13 12/15] test: dm: Add test cases for FWU Metadata uclass

2022-10-10 Thread Etienne Carriere
Hi Sughosh,

On Fri, 7 Oct 2022 at 05:16, Sughosh Ganu  wrote:
>
> hi Etienne,
>
> On Thu, 6 Oct 2022 at 19:36, Etienne Carriere
>  wrote:
> >
> > 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/tools/Makefile b/tools/Makefile
> > > index 34a1aa7a8b..27687d5cd9 100644
> > > --- a/tools/Makefile
> > > +++ b/tools/Makefile
> > > @@ -74,7 +74,7 @@ mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o
> > >  hostprogs-y += dumpimage mkimage
> > >  hostprogs-$(CONFIG_TOOLS_LIBCRYPTO) += fit_info fit_check_sign
> > >
> > > -hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST) += file2include
> > > +hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_FWU_MDATA_GPT_BLK) += 
> > > file2include
> >
> > Late catch, my apologies. This won't work when both switches are enable.
>
> Okay, although this is not an issue in the current upstream, as
> CONFIG_CMD_BOOTEFI_SELFTEST is not enabled in the sandbox64 defconfig.
>
> > Prefer something like:
> >
> > +ifneq (,$(filter y,$(CONFIG_CMD_BOOTEFI_SELFTEST) 
> > $(CONFIG_FWU_MDATA_GPT_BLK)))
> > +hostprogs-y += file2include
> > +endif
>
> Okay. Btw, any issue with having something like this?
>
> ifneq ($(CONFIG_CMD_BOOTEFI_SELFTEST)$(CONFIG_FWU_MDATA_GPT_BLK),)
> hostprogs-y += file2include
> endif

I'm not shure. I prefer to ask maintainers whether they prefer
ifneq ($(CONFIG_FOO)$(CONFIG_BAR),)
or
ifneq (,$(filter y,$(CONFIG_FOO) $(CONFIG_BAR)))
for such boolean config switches.

br,
etienne

>
> -sughosh
>
> >
> > br,
> > etienne
> >
> > >
> > >  FIT_OBJS-y := fit_common.o fit_image.o image-host.o boot/image-fit.o
> > >  FIT_SIG_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := image-sig-host.o 
> > > boot/image-fit-sig.o
> > > --
> > > 2.34.1
> > >


Re: [PATCH v13 12/15] test: dm: Add test cases for FWU Metadata uclass

2022-10-06 Thread Etienne Carriere
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 = <>;
> +   };
>  };
>
>  #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(, 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 image */

Re: [PATCH v12 06/15] FWU: Add helper functions for accessing FWU metadata

2022-10-03 Thread Etienne Carriere
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(_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, ))
> +   continue;
> +   uuid_str_to_bin(info.uuid, unique_part_guid.b,
> +   UUID_STR_FORMAT_GUID);
> +
> +   if (!guidcmp(_part_guid, image_guid))
> +   return i;
> +   }
> +
> +   log_err("No partition fo

Re: [PATCH v10 10/15] FWU: Add support for the FWU Multi Bank Update feature

2022-10-03 Thread Etienne Carriere
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 v11 15/15] FWU: doc: Add documentation for the FWU feature

2022-09-30 Thread Etienne Carriere
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 v11 03/15] FWU: Add FWU metadata access driver for GPT partitioned block devices

2022-09-30 Thread Etienne Carriere
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, ))
> +   continue;
> +   uuid_str_to_bin(info.type_guid, part_type_guid.b,
> +   UUID_STR_FORMAT_GUID);
> +
> +   if (nparts < 2 && !guidcmp(_mdata_guid, _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 = -EINVAL;
> +   } else {
> +   r

Re: [PATCH v11 02/15] FWU: Add FWU metadata structure and driver for accessing metadata

2022-09-29 Thread Etienne Carriere
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 = >version;
> +   mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> +
> +   return ops->update_mdata(dev, mdata);

Re: [PATCH v11 05/15] stm32mp1: dk2: Add image information for capsule updates

2022-09-29 Thread Etienne Carriere
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(_images[0].image_type_id, _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] tee: optee: discover services dependent on tee-supplicant

2022-09-28 Thread Etienne Carriere
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, , 1, );
> 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, _size, tee_sess);
> +   ret = __enum_services(dev, NULL, _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, _size, tee_sess);
> +   ret = __enum_services(dev, *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, _sess);
> if (ret)
> return ret;
>
> -   ret = enum_services(dev, _list, _count, tee_sess);
> +   ret = enum_services(dev, _list, _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, _list, _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

2022-09-28 Thread Etienne Carriere
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 
> > > > > >>>>>>

[PATCH] tee: optee: discover services dependent on tee-supplicant

2022-09-28 Thread Etienne Carriere
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, , 1, );
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, _size, tee_sess);
+   ret = __enum_services(dev, NULL, _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, _size, tee_sess);
+   ret = __enum_services(dev, *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, _sess);
if (ret)
return ret;
 
-   ret = enum_services(dev, _list, _count, tee_sess);
+   ret = enum_services(dev, _list, _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, _list, _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 v10 10/15] FWU: Add support for the FWU Multi Bank Update feature

2022-09-28 Thread Etienne Carriere
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(_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 this 

Re: [PATCH v10 15/15] FWU: doc: Add documentation for the FWU feature

2022-09-27 Thread Etienne Carriere
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. 

Re: [PATCH v10 07/15] FWU: STM32MP1: Add support to read boot index from backup register

2022-09-27 Thread Etienne Carriere
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 03/15] FWU: Add FWU metadata access driver for GPT partitioned block devices

2022-09-27 Thread Etienne Carriere
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;
> > > +  

Re: [PATCH v4] tee: optee: rework TA bus scanning code

2022-09-22 Thread Etienne Carriere
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
> > > >>>>>> + { .drv_name = "ftpm_

Re: [PATCH v4] tee: optee: rework TA bus scanning code

2022-09-22 Thread Etienne Carriere
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
> > > >>>>>> + { .drv_name =

Re: [PATCH v4] tee: optee: rework TA bus scanning code

2022-09-22 Thread Etienne Carriere
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)
> >>>>>&g

Re: [PATCH 1/1] efi_driver: don't bind internal block devices

2022-09-09 Thread Etienne Carriere
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,
> , 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] [RFC] lib: efi_loader: don't delete invalid handles

2022-09-09 Thread Etienne Carriere
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, , this->driver_binding_handle,
> controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)
>EFI: 20 returned by systab.boottime->open_protocol(
> controller_handle, bp->ops->prot

Re: [PATCH 1/1] efi_selftest: supply EFI binary for ExitBootServices

2022-09-08 Thread Etienne Carriere
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(_size, NULL, _key,
> _size,
> +  _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 **)_map);
> +   if (ret != EFI_SUCCESS) {
> +   error(u"AllocatePool did not return EFI_SUCCESS\r\n");
> +   return ret;
> +   }
> +   ret = boottime->get_memory_map(_size, memory_map, _key,
> +  _size, _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;
> +}
> +
> +/**
> + * efi_main() - entry point of the EFI application.
> + *
> + * @handle:handle of the 

Re: [PATCH] [RFC] lib: efi_loader: don't delete invalid handles

2022-09-08 Thread Etienne Carriere
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(>link);
> >   free(handle);
> >   }
>
>


  1   2   3   4   >