Re: [RFC PATCH 1/1] eficonfig: Add a 'scan-only' mode in eficonfig
On Thu, Mar 02, 2023 at 11:21:05AM +0900, Masahisa Kojima wrote: > Hi Ilias, > > On Wed, 1 Mar 2023 at 23:44, Ilias Apalodimas > wrote: > > > > eficonfig will automatically scan and add Boot variables on launch. > > It will also perform automatic management of the automatically added > > variables (e.g it might decide to delete a boot option if the DP > > disappears). This functionality is useful outside the context of > > eficonfig as well. > > > > So let's add a -a flag to eficonfig that will only perform the > > automatic variable management and exit. That would allow users > > to define a bootcmd along the lines of 'eficonfig -a && bootefi bootmgr', > > that matches the §3.5.1.1 'Removable Media Boot Behavior' behaviour > > described in the EFI spec. > > > > Open questions: > > - Is this ok to add on eficonfig? Similar functionality is described in the > > EFI > > spec as part of the efibootmgr > > - Having the functionality on the command gives us the flexibility to run > > the > > run the command when needed. Alternatively we could move it to the > > efibootmgr > > and hide it behing a Kconfig option > > In current implementation, "bootmenu" and "eficonfig" invoke this > automatic load option > management function, but I think "bootmenu" should not have responsibility for > load option management. > So I'll vote for moving this automatic load option management into efibootmgr, > then it is invoked in efi subsystem initialization. Basically +1, but I think that we can implement this kind of action by using 'event' hook as "removable media support" itself is implemented. -Takahiro Akashi > Regards, > Masahisa Kojima > > > Signed-off-by: Ilias Apalodimas > > --- > > cmd/eficonfig.c | 23 --- > > 1 file changed, 20 insertions(+), 3 deletions(-) > > > > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c > > index 720f52b48b8c..9b6631816997 100644 > > --- a/cmd/eficonfig.c > > +++ b/cmd/eficonfig.c > > @@ -2693,10 +2693,18 @@ static int do_eficonfig(struct cmd_tbl *cmdtp, int > > flag, int argc, char *const a > > { > > efi_status_t ret; > > struct efimenu *efi_menu; > > + bool exit_on_scan = false; > > > > - if (argc > 1) > > + if (argc > 2) > > return CMD_RET_USAGE; > > > > + if (argc > 1) { > > + if (!strcmp(argv[1], "-a")) > > + exit_on_scan = true; > > + else > > + return CMD_RET_FAILURE; > > + } > > + > > ret = efi_init_obj_list(); > > if (ret != EFI_SUCCESS) { > > log_err("Error: Cannot initialize UEFI sub-system, r = > > %lu\n", > > @@ -2713,6 +2721,9 @@ static int do_eficonfig(struct cmd_tbl *cmdtp, int > > flag, int argc, char *const a > > if (ret != EFI_SUCCESS && ret != EFI_NOT_FOUND) > > return ret; > > > > + if (exit_on_scan) > > + return EFI_SUCCESS; > > + > > while (1) { > > efi_menu = > > eficonfig_create_fixed_menu(maintenance_menu_items, > > > > ARRAY_SIZE(maintenance_menu_items)); > > @@ -2734,8 +2745,14 @@ static int do_eficonfig(struct cmd_tbl *cmdtp, int > > flag, int argc, char *const a > > return CMD_RET_SUCCESS; > > } > > > > +static char eficonfig_help_text[] = > > + " - UEFI menu to configure UEFI variables\n" > > + "\n" > > + "eficonfig - Spawn the configuration menu\n" > > + " -a Scan, configure Boot variables and exit\n"; > > + > > U_BOOT_CMD( > > - eficonfig, 1, 0, do_eficonfig, > > + eficonfig, 2, 0, do_eficonfig, > > "provide menu-driven UEFI variable maintenance interface", > > - "" > > + eficonfig_help_text > > ); > > -- > > 2.39.2 > >
Re: [PATCH v2] disk: Use a helper function to reduce duplication
On Mon, Mar 20, 2023 at 09:31:58AM +0200, Ilias Apalodimas wrote: > Hi Simon, > > Patch looks good, but isn't the new function name a bit misleading? > Something like blk_part_find_start() sounds a bit more descriptive, or am I > missing something? I don't think that the helper function works as my original code does. > Cheers > /Ilias > > On Mon, Mar 20, 2023 at 08:29:57AM +1300, Simon Glass wrote: > > Reduce the duplicated code slightly by using a helper function to handle > > the common code. > > > > This reduces the code size very slightly. > > > > Signed-off-by: Simon Glass > > --- > > > > Changes in v2: > > - Rebase to -next > > > > disk/disk-uclass.c | 46 +- > > 1 file changed, 25 insertions(+), 21 deletions(-) > > > > diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c > > index d32747e2242d..7f1fd80b2248 100644 > > --- a/disk/disk-uclass.c > > +++ b/disk/disk-uclass.c > > @@ -65,26 +65,38 @@ int part_create_block_devices(struct udevice *blk_dev) > > return 0; > > } > > > > +static int blk_part_setup(struct udevice *dev, lbaint_t *startp, > > + lbaint_t blkcnt) > > +{ > > + struct disk_part *part; > > + > > + part = dev_get_uclass_plat(dev); > > + if (*startp >= part->gpt_part_info.size) > > + return -E2BIG; > > + > > + if (*startp + blkcnt > part->gpt_part_info.size) > > + blkcnt = part->gpt_part_info.size - *startp; > > + *startp += part->gpt_part_info.start; > > + > > + return 0; > > +} > > + > > static ulong part_blk_read(struct udevice *dev, lbaint_t start, > >lbaint_t blkcnt, void *buffer) > > { > > struct udevice *parent; > > - struct disk_part *part; > > const struct blk_ops *ops; > > + int ret; > > > > parent = dev_get_parent(dev); > > ops = blk_get_ops(parent); > > if (!ops->read) > > return -ENOSYS; > > > > - part = dev_get_uclass_plat(dev); > > - if (start >= part->gpt_part_info.size) > > + ret = blk_part_setup(dev, &start, blkcnt); > > + if (ret) > > return 0; > > > > - if ((start + blkcnt) > part->gpt_part_info.size) > > - blkcnt = part->gpt_part_info.size - start; > > - start += part->gpt_part_info.start; > > - We cannot read out more blocks than the size of the partition. > > return ops->read(parent, start, blkcnt, buffer); So blkcnt must also be adjusted, otherwise we may see extra blocks beyond the partition boundary. -Takahiro Akashi > > } > > > > @@ -92,22 +104,18 @@ static ulong part_blk_write(struct udevice *dev, > > lbaint_t start, > > lbaint_t blkcnt, const void *buffer) > > { > > struct udevice *parent; > > - struct disk_part *part; > > const struct blk_ops *ops; > > + int ret; > > > > parent = dev_get_parent(dev); > > ops = blk_get_ops(parent); > > if (!ops->write) > > return -ENOSYS; > > > > - part = dev_get_uclass_plat(dev); > > - if (start >= part->gpt_part_info.size) > > + ret = blk_part_setup(dev, &start, blkcnt); > > + if (ret) > > return 0; > > > > - if ((start + blkcnt) > part->gpt_part_info.size) > > - blkcnt = part->gpt_part_info.size - start; > > - start += part->gpt_part_info.start; > > - > > return ops->write(parent, start, blkcnt, buffer); > > } > > > > @@ -115,22 +123,18 @@ static ulong part_blk_erase(struct udevice *dev, > > lbaint_t start, > > lbaint_t blkcnt) > > { > > struct udevice *parent; > > - struct disk_part *part; > > const struct blk_ops *ops; > > + int ret; > > > > parent = dev_get_parent(dev); > > ops = blk_get_ops(parent); > > if (!ops->erase) > > return -ENOSYS; > > > > - part = dev_get_uclass_plat(dev); > > - if (start >= part->gpt_part_info.size) > > + ret = blk_part_setup(dev, &start, blkcnt); > > + if (ret) > > return 0; > > > > - if ((start + blkcnt) > part->gpt_part_info.size) > > - blkcnt = part->gpt_part_info.size - start; > > - start += part->gpt_part_info.start; > > - > > return ops->erase(parent, start, blkcnt); > > } > > > > -- > > 2.40.0.rc1.284.g88254d51c5-goog > >
Re: [PATCH 01/10] firmware: scmi: implement SCMI base protocol
On Thu, Jun 29, 2023 at 08:09:45PM +0100, Simon Glass wrote: > Hi AKASHI, > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > wrote: > > > > 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 > > --- > > drivers/firmware/scmi/Makefile | 1 + > > drivers/firmware/scmi/base.c | 517 + > > include/dm/uclass-id.h | 1 + > > include/scmi_protocols.h | 201 - > > 4 files changed, 718 insertions(+), 2 deletions(-) > > 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/include/dm/uclass-id.h b/include/dm/uclass-id.h > > index 307ad6931ca7..f7a110852321 100644 > > --- a/include/dm/uclass-id.h > > +++ b/include/dm/uclass-id.h > > @@ -116,6 +116,7 @@ enum uclass_id { > > UCLASS_RNG, /* Random Number Generator */ > > UCLASS_RTC, /* Real time clock device */ > > UCLASS_SCMI_AGENT, /* Interface with an SCMI server */ > > + UCLASS_SCMI_BASE, /* Interface for SCMI Base protocol */ > > UCLASS_SCSI,/* SCSI device */ > > UCLASS_SERIAL, /* Serial UART */ > > UCLASS_SIMPLE_BUS, /* Bus with child devices */ > > diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h > > index a220cb2a91ad..769041654534 100644 > > --- a/include/scmi_protocols.h > > +++ b/include/scmi_protocols.h > > @@ -15,6 +15,8 @@ > > * https://developer.arm.com/docs/den0056/b > > */ > > > > +#define SCMI_BASE_NAME_LENGTH_MAX 16 > > + > > enum scmi_std_protocol { > > SCMI_PROTOCOL_ID_BASE = 0x10, > > SCMI_PROTOCOL_ID_POWER_DOMAIN = 0x11, > > @@ -41,12 +43,207 @@ enum scmi_status_code { > > }; > > > > /* > > - * Generic message IDs > > + * SCMI Base Protocol > > */ > > -enum scmi_discovery_id { > > +#define SCMI_BASE_PROTOCOL_VERSION 0x2 > > + > > +enum scmi_base_message_id { > > SCMI_PROTOCOL_VERSION = 0x0, > > SCMI_PROTOCOL_ATTRIBUTES = 0x1, > > SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x2, > > + SCMI_BASE_DISCOVER_VENDOR = 0x3, > > + SCMI_BASE_DISCOVER_SUB_VENDOR = 0x4, > > + SCMI_BASE_DISCOVER_IMPL_VERSION = 0x5, > > + SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x6, > > + SCMI_BASE_DISCOVER_AGENT = 0x7, > > + SCMI_BASE_NOTIFY_ERRORS = 0x8, > > + SCMI_BASE_SET_DEVICE_PERMISSIONS = 0x9, > > + SCMI_BASE_SET_PROTOCOL_PERMISSIONS = 0xa, > > + SCMI_BASE_RESET_AGENT_CONFIGURATION = 0xb, > > +}; > > + > > +/** > > + * struct scmi_protocol_version_out - Response for SCMI_PROTOCOL_VERSION > > + * command > > + * @status:SCMI command status > > + * @version: Protocol version > > + */ > > +struct scmi_protocol_version_out { > > + s32 status; > > + u32 version; > > +}; > > + > > +/** > > + * struct scmi_protocol_attrs_out - Response for SCMI_PROTOCOL_ATTRIBUTES > > + * command > > + * @status:SCMI command status > > + * @attributes:Protocol attributes or implementation details > > + */ > > +struct scmi_protocol_attrs_out { > > + s32 status; > > + u32 attributes; > > +}; > > + > > +#define SCMI_PROTOCOL_ATTRS_NUM_AGENTS(attributes) \ > > + (((attributes) & GENMASK(15, 8)) >> 8) > > +#define SCMI_PROTOCOL_ATTRS_NUM_PROTOCOLS(attributes) \ > > + ((attributes) & GENMASK(7, 0)) > > + > > +/** > > + * struct scmi_protocol_msg_attrs_out - Response for &
Re: [PATCH 08/10] cmd: add scmi command for SCMI firmware
On Thu, Jun 29, 2023 at 08:10:00PM +0100, Simon Glass wrote: > Hi AKASHI, > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > wrote: > > > > This command, "scmi", provides a command line interface to various SCMI > > protocols. It supports at least initially SCMI base protocol with the sub > > command, "base", and is intended mainly for debug purpose. > > > > Signed-off-by: AKASHI Takahiro > > --- > > cmd/Kconfig | 8 ++ > > cmd/Makefile | 1 + > > cmd/scmi.c | 373 +++ > > 3 files changed, 382 insertions(+) > > create mode 100644 cmd/scmi.c > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 02e54f1e50fe..065470a76295 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -2504,6 +2504,14 @@ 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 protocols, > > + including Base protocol. > > Please mention what is SCMI I will give a full spelling. > > 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 ..c97f77e97d95 > > --- /dev/null > > +++ b/cmd/scmi.c > > @@ -0,0 +1,373 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * SCMI utility command > > + * > > + * Copyright (c) 2023 Linaro Limited > > + * Author: AKASHI Takahiro > > + */ > > + > > +#include > > +#include > > +#include > > +#include /* uclass_get_device */ > > Goes before linux/bitfield.h Can you tell me why? > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +static struct udevice *agent; > > +static struct udevice *base_proto; > > +static const struct scmi_base_ops *ops; > > + > > +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"}, > > +}; > > + > > +/** > > + * scmi_convert_id_to_string() - get the name of SCMI protocol > > + * > > + * @id:Protocol ID > > + * > > + * Get the printable name of the protocol, @id > > + * > > + * Return: Name string on success, NULL on failure > > + */ > > +static const char *scmi_convert_id_to_string(enum scmi_std_protocol id) > > scmi_lookup_id? Not sure your intention. The name above gives us exactly what this function does for pretty printing instead of a number. I think that 'lookup' implies we try to determine if the id exists or not. > > +{ > > + 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_base_info() - get the information of SCMI services > > + * > > + * @cmdtp: Command table > > + * @flag: Comm
Re: [PATCH 07/10] test: dm: add SCMI base protocol test
On Thu, Jun 29, 2023 at 08:09:58PM +0100, Simon Glass wrote: > Hi AKASHI, > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > wrote: > > > > 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 > > --- > > test/dm/scmi.c | 112 + > > 1 file changed, 112 insertions(+) > > > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > > index 881be3171b7c..563017bb63e0 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,115 @@ 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; > > + const struct scmi_base_ops *ops; > > + u32 version, num_agents, num_protocols, impl_version; > > + u32 attributes, agent_id; > > + char vendor[SCMI_BASE_NAME_LENGTH_MAX], > > +agent_name[SCMI_BASE_NAME_LENGTH_MAX]; > > + u8 *protocols; > > + int ret; > > + > > + /* preparation */ > > + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", > > + &agent_dev)); > > + ut_assertnonnull(agent_dev); > > + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev)); > > + ut_assertnonnull(base = scmi_get_protocol(agent_dev, > > + SCMI_PROTOCOL_ID_BASE)); > > + ut_assertnonnull(ops = dev_get_driver_ops(base)); > > + > > + /* version */ > > + ret = (*ops->protocol_version)(base, &version); > > Can you add uclass helpers to call each of the methods? That is how it > is commonly done. You should not be calling ops->xxx directly here. Yes, I will add inline functions instead. -Takahiro Akashi > > + ut_assertok(ret); > > + ut_asserteq(priv->version, version); > > + > > + /* protocol attributes */ > > + ret = (*ops->protocol_attrs)(base, &num_agents, &num_protocols); > > + ut_assertok(ret); > > + ut_asserteq(priv->num_agents, num_agents); > > + ut_asserteq(priv->num_protocols, num_protocols); > > + > > + /* discover vendor */ > > + ret = (*ops->base_discover_vendor)(base, vendor); > > + ut_assertok(ret); > > + ut_asserteq_str(priv->vendor, vendor); > > + > > + /* message attributes */ > > + ret = (*ops->protocol_message_attrs)(base, > > +SCMI_BASE_DISCOVER_SUB_VENDOR, > > +&attributes); > > + ut_assertok(ret); > > + ut_assertok(attributes); > > + > > + /* discover sub vendor */ > > + ret = (*ops->base_discover_sub_vendor)(base, vendor); > > + ut_assertok(ret); > > + ut_asserteq_str(priv->sub_vendor, vendor); > > + > > + /* impl version */ > > + ret = (*ops->base_discover_impl_version)(base, &impl_version); > > + ut_assertok(ret); > > + ut_asserteq(priv->impl_version, impl_version); > > + > > + /* discover agent (my self) */ > > + ret = (*ops->base_discover_agent)(base, 0x, > > + &agent_id, agent_name); > > + ut_assertok(ret); > > + ut_asserteq(priv->agent_id, agent_id); > > + ut_asserteq_str(priv->agent_name, agent_name); > > + > > + /* discover protocols */ > > + ret = (*ops->base_discover_list_protocols)(base, &protocols); > > + ut_asserteq(num_protocols, ret); > > + ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * > > num_protocols); > > + free(protocols); > > + > > + /* > > +* NOTE: Sandbox SCMI driver handles device-0 only. It supports > > setting > > +* access and protocol permission
Re: [PATCH 09/10] doc: cmd: add documentation for scmi
On Thu, Jun 29, 2023 at 08:10:02PM +0100, Simon Glass wrote: > Hi AKASHI, > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > wrote: > > > > This is a help text for scmi command. > > > > Signed-off-by: AKASHI Takahiro > > --- > > doc/usage/cmd/scmi.rst | 98 ++ > > 1 file changed, 98 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 ..20cdae4b877d > > --- /dev/null > > +++ b/doc/usage/cmd/scmi.rst > > @@ -0,0 +1,98 @@ > > +.. SPDX-License-Identifier: GPL-2.0+: > > + > > +scmi command > > + > > + > > +Synopsis > > + > > + > > +:: > > + > > +scmi base info > > +scmi base perm_dev > > +scmi base perm_proto > > +scmi base reset > > + > > +Description > > +--- > > + > > +The scmi command is used to access and operate on SCMI server. > > + > > +scmi base info > > +~~ > > +Show base information about SCMI server and supported protocols > > + > > +scmi base perm_dev > > +~~ > > +Allow or deny access permission to the device > > + > > +scmi base perm_proto > > + > > +Allow or deny access to the protocol on the device > > + > > +scmi base reset > > +~~~ > > +Reset the existing configurations > > + > > +Parameters are used as follows: > > + > > + > > +Agent ID > > what is this? I thought that the meaning was trivial in SCMI context. Will change it to "SCMI Agent ID". > > + > > + > > +Device ID > > what is this? Again, will change it to "SCMI Device ID". > > + > > + > > +Protocol ID, should not be 0x10 (base protocol) > > what is this? Please add more detail Again, will change it to "SCMI Protocol ID". I think that users should be familiar with those terms if they want to use these interfaces. > > + > > + > > +Flags to control the action. See SCMI specification for > > +defined values. > > ? > > Please add the flags here, or at the very least provide a URL and page > number, etc. I intentionally avoid providing details here because a set of flags acceptable to a specific SCMI server may depend on the server and its implementation version. The interface on U-Boot is just a wrapper to make a call to SCMI server via a transport layer and doesn't care what the parameters means. That said, I agree to referring to a URL to SCMI specification somewhere in this document. Thanks, -Takahiro Akashi > > + > > +Example > > +--- > > + > > +Obtain basic information about SCMI server: > > + > > +:: > > + > > +=> scmi base 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 base perm_dev 1 0 1 > > + > > +Reset configurations with all access permission settings retained: > > + > > +:: > > + > > +=> scmi base 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. > > -- > > 2.41.0 > > > > Regards, > Simon
Re: [PATCH] efi_driver: fix duplicate efiblk#0 issue
On Mon, Jul 03, 2023 at 11:47:18AM +0900, Masahisa Kojima wrote: > The devnum value of the blk_desc structure starts from 0, > current efi_bl_create_block_device() function creates > two "efiblk#0" devices for the cases that blk_find_max_devnum() > returns -ENODEV and blk_find_max_devnum() returns 0(one device > found in this case). > > The devnum value for the "efiblk" name needs to be incremented. > > Signed-off-by: Masahisa Kojima > --- > lib/efi_driver/efi_block_device.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/lib/efi_driver/efi_block_device.c > b/lib/efi_driver/efi_block_device.c > index add00eeebb..e37bfe6e80 100644 > --- a/lib/efi_driver/efi_block_device.c > +++ b/lib/efi_driver/efi_block_device.c > @@ -129,6 +129,8 @@ efi_bl_create_block_device(efi_handle_t handle, void > *interface) > devnum = 0; > else if (devnum < 0) > return EFI_OUT_OF_RESOURCES; > + else > + devnum++; /* device found, note that devnum starts from 0 */ So we can use blk_next_free_devnum() instead. -Takahiro Akashi > name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */ > if (!name) > -- > 2.34.1 >
Re: [PATCH 08/10] cmd: add scmi command for SCMI firmware
On Mon, Jul 03, 2023 at 02:30:54PM +0100, Simon Glass wrote: > Hi, > > On Mon, 3 Jul 2023 at 01:55, AKASHI Takahiro > wrote: > > > > On Thu, Jun 29, 2023 at 08:10:00PM +0100, Simon Glass wrote: > > > Hi AKASHI, > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > wrote: > > > > > > > > This command, "scmi", provides a command line interface to various SCMI > > > > protocols. It supports at least initially SCMI base protocol with the > > > > sub > > > > command, "base", and is intended mainly for debug purpose. > > > > > > > > Signed-off-by: AKASHI Takahiro > > > > --- > > > > cmd/Kconfig | 8 ++ > > > > cmd/Makefile | 1 + > > > > cmd/scmi.c | 373 +++ > > > > 3 files changed, 382 insertions(+) > > > > create mode 100644 cmd/scmi.c > > > > > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > > > index 02e54f1e50fe..065470a76295 100644 > > > > --- a/cmd/Kconfig > > > > +++ b/cmd/Kconfig > > > > @@ -2504,6 +2504,14 @@ 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 > > > > protocols, > > > > + including Base protocol. > > > > > > Please mention what is SCMI > > > > I will give a full spelling. > > > > > > 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 ..c97f77e97d95 > > > > --- /dev/null > > > > +++ b/cmd/scmi.c > > > > @@ -0,0 +1,373 @@ > > > > +// SPDX-License-Identifier: GPL-2.0+ > > > > +/* > > > > + * SCMI utility command > > > > + * > > > > + * Copyright (c) 2023 Linaro Limited > > > > + * Author: AKASHI Takahiro > > > > + */ > > > > + > > > > +#include > > > > +#include > > > > +#include > > > > +#include /* uclass_get_device */ > > > > > > Goes before linux/bitfield.h > > > > Can you tell me why? > > It is just a convention: > https://u-boot.readthedocs.io/en/latest/develop/codingstyle.html#include-files Okay. > > > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > +#include > > > > + > > > > +static struct udevice *agent; > > > > +static struct udevice *base_proto; > > > > +static const struct scmi_base_ops *ops; > > > > + > > > > +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"}, > > > > +}; > > > > + > > > > +/** > > > > + * scmi_convert_id_to_string() - get the name of SCMI protocol > > > > + * > > > > + * @id:Protocol ID > > > > + * > > > > + * Get the printable name of the protocol, @id > > > > + * > > > > + * Return: Name string on success, NULL on failure > > > > + */ > > > > +static const char *scmi_convert_id_to_string(enum scmi_std_protocol id) > > > > > > scmi_lookup_id? > > > > Not sure your intention. > > The name above gives us exactly what this function does for pretty printing > > instead of a number. > > I think that 'lookup' implies we try to determine if the id exists or not. > > I am just trying to avoid the code turning into Java :-) Java? > How about scmi_get_name() ? Well, more specifically scmi_get_protocol_name()? -Takahiro Akashi > Regards, > Simon
Re: [PATCH 09/10] doc: cmd: add documentation for scmi
Hi Simon, On Mon, Jul 03, 2023 at 02:30:55PM +0100, Simon Glass wrote: > Hi , > > On Mon, 3 Jul 2023 at 02:19, AKASHI Takahiro > wrote: > > > > On Thu, Jun 29, 2023 at 08:10:02PM +0100, Simon Glass wrote: > > > Hi AKASHI, > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > wrote: > > > > > > > > This is a help text for scmi command. > > > > > > > > Signed-off-by: AKASHI Takahiro > > > > --- > > > > doc/usage/cmd/scmi.rst | 98 ++ > > > > 1 file changed, 98 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 ..20cdae4b877d > > > > --- /dev/null > > > > +++ b/doc/usage/cmd/scmi.rst > > > > @@ -0,0 +1,98 @@ > > > > +.. SPDX-License-Identifier: GPL-2.0+: > > > > + > > > > +scmi command > > > > + > > > > + > > > > +Synopsis > > > > + > > > > + > > > > +:: > > > > + > > > > +scmi base info > > > > +scmi base perm_dev > > > > +scmi base perm_proto > > > > +scmi base reset > > > > + > > > > +Description > > > > +--- > > > > + > > > > +The scmi command is used to access and operate on SCMI server. > > > > + > > > > +scmi base info > > > > +~~ > > > > +Show base information about SCMI server and supported protocols > > > > + > > > > +scmi base perm_dev > > > > +~~ > > > > +Allow or deny access permission to the device > > > > + > > > > +scmi base perm_proto > > > > + > > > > +Allow or deny access to the protocol on the device > > > > + > > > > +scmi base reset > > > > +~~~ > > > > +Reset the existing configurations > > > > + > > > > +Parameters are used as follows: > > > > + > > > > + > > > > +Agent ID > > > > > > what is this? > > > > I thought that the meaning was trivial in SCMI context. > > Will change it to "SCMI Agent ID". > > What is SCMI? Really you should explain and link to information about > things you mention in documentation. How else is anyone supposed to Generally yes, but please note that SCMI and related drivers are already there in U-Boot. For instance, see drivers/firmware/scmi/Kconfig. I don't think we need any more explanation about what is SCMI everywhere the word, "SCMI", appears. > figure out what you are talking about? Again, those who don't know about SCMI and if SCMI server is installed on their systems will never use this command. > > "SCMI Agent ID" doesn't tell us much. What form does it take? Is it a > string? How do you find it out? While I still believe that What SCMI agent ID means is trivial for those who read the SCMI specification, I will give a short description about possible values. > > > > > > > > + > > > > + > > > > +Device ID > > > > > > what is this? > > > > Again, will change it to "SCMI Device ID". > > That doesn't help much. The purpose of documentation is to explain > things for people who don't already know it. We need to try to be as > helpful as possible. The same above. Please note that the definition of "device (ID)", except its data type, is out of scope of SCMI specification. It doesn't describe any means by which values be identified/retrieved. > > > > > > + > > > > + > > > > +Protocol ID, should not be 0x10 (base protocol) > > > > > > what is this? Please add more detail > > > > Again, will change it to "SCMI Protocol ID". > > I think that users should be familiar with those terms > > if they want to use these interfaces. > > Maybe, but it still isn't clear what it is. A string? Will add a short description about its data type/format. > It is confusing > that the command ID is also a protocol ID. Yes, I know, but the confusion exists in SCMI specification. It sometimes seems to use both words almost interchangeably, even in a single context. For instance, the section
Re: [PATCH 07/10] test: dm: add SCMI base protocol test
Hi Simon, On Mon, Jul 03, 2023 at 02:30:57PM +0100, Simon Glass wrote: > Hi, > > On Mon, 3 Jul 2023 at 01:57, AKASHI Takahiro > wrote: > > > > On Thu, Jun 29, 2023 at 08:09:58PM +0100, Simon Glass wrote: > > > Hi AKASHI, > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > wrote: > > > > > > > > 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 > > > > --- > > > > test/dm/scmi.c | 112 + > > > > 1 file changed, 112 insertions(+) > > > > > > > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > > > > index 881be3171b7c..563017bb63e0 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,115 @@ 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; > > > > + const struct scmi_base_ops *ops; > > > > + u32 version, num_agents, num_protocols, impl_version; > > > > + u32 attributes, agent_id; > > > > + char vendor[SCMI_BASE_NAME_LENGTH_MAX], > > > > +agent_name[SCMI_BASE_NAME_LENGTH_MAX]; > > > > + u8 *protocols; > > > > + int ret; > > > > + > > > > + /* preparation */ > > > > + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", > > > > + &agent_dev)); > > > > + ut_assertnonnull(agent_dev); > > > > + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev)); > > > > + ut_assertnonnull(base = scmi_get_protocol(agent_dev, > > > > + > > > > SCMI_PROTOCOL_ID_BASE)); > > > > + ut_assertnonnull(ops = dev_get_driver_ops(base)); > > > > + > > > > + /* version */ > > > > + ret = (*ops->protocol_version)(base, &version); > > > > > > Can you add uclass helpers to call each of the methods? That is how it > > > is commonly done. You should not be calling ops->xxx directly here. > > > > Yes, I will add inline functions instead. > > I don't mean inline...see all the other uclasses which define a Okay, I will *real* functions. > function which is implemented in the uclass. It is confusing when one > uclass does something different. People might copy this style and then > the code base diverges. Did you not notice this when looking around > the source tree? But one concern came up in my mind. Contrary to ordinary "device controllers", there exists only a single implementation of driver for each of "udevice"'s associated with SCMI protocols including the base protocol. So if I follow your suggestion, the code (base.c) might look like: === static int __scmi_base_discover_vendor(struct udevice *dev, u8 *vendor) { ... } struct scmi_base_ops scmi_base_ops = { .base_discover_vendor = __scmi_base_discover_vendor, } int scmi_base_discover_vendor(struct udevice *dev, u8 *vendor) { struct scmi_base_ops *ops; ops = scmi_base_dev_ops(dev); return ops->base_discover_vendor(dev, vendor); } === We will have to have similar definitions for every operation in ops. It looks quite weird to me as there are always pairs of functions, like __scmi_base_discover_vendor() and scmi_base_discover_vendor(). We can avoid this redundant code easily by eliminating "ops" abstraction. But as far as I remember, you insist that every driver that complies to U-Boot driver model should have a "ops". What do you make of this? Thanks -Takahiro Akashi > Regards, > Simon
Re: EFI Secure boot default keys
Hi, On Wed, Jul 05, 2023 at 01:24:32PM +, Neil Jones wrote: > >> Please can someone describe the format of the file needed for the default > >> / built-in EFI secure boot keys (ubootefi.var) > >> > >> The only docs I have found suggest its best to enroll the keys from within > >> u-boot onto some removable media, then copy this off and use this as the > >> default, this is not very helpful and doesn't work for me: > >> > >> => fatload mmc 0:1 ${loadaddr} PK.aut > >> 2053 bytes read in 18 ms (111.3 KiB/s) > >> => setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize PK > >> setenv - set environment variables > >> > >> Usage: > >> setenv setenv [-f] name value ... > >> - [forcibly] set environment variable 'name' to 'value ...' > >> setenv [-f] name > >> - [forcibly] delete environment variable 'name' > >> > >> my setenv doesn't support all the extra switches ? This is with 2022.04, > >> all other EFI options seem to be in this release and I can boot unsigned > >> EFI images ok. > > > >Please turn on CONFIG_CMD_NVEDIT_EFI when building your U-Boot. > > > >This option was disabled by the commit: > >commit 3b728f8728fa (tag: efi-2020-01-rc1) > >Author: Heinrich Schuchardt > >Date: Sun Oct 6 15:44:22 2019 +0200 > > > >cmd: disable CMD_NVEDIT_EFI by default > > > >The binary size of efi has grown much since in the past, though. > > > >-Takahiro Akashi > > Thanks, I have secure boot working now. A tool to generate the ubootefi.var > offline or even just a description of the file format would be very useful. Thank you for the suggestion. While I'd like to defer to Heinrich, the C definition of the file format can be found as struct efi_var_file in include/efi_variable.h > I have noticed one issue when using ubootefi.var on mmc, when I switch boot > order it wipes out the keys and I have to re-enrol them: > > => fatls mmc 0:1 > 3040 ubootefi.var > > 1 file(s), 0 dir(s) I'm not sure that secure boot related variables have been loaded at this point. Anyhow, please try to enable CONFIG_EFI_VARIABLES_PRESEED with EFI_VAR_FILE_NAME set. Otherwise, those variables will never be restored. (This is another topic that are not described in doc/develop/uefi.) Thanks, -Takahiro Akashi > => efidebug boot order 2 1 > => fatls mmc 0:1 > 440 ubootefi.var > > (Size drops from 3040 to 440 bytes and keys have gone) > > > > > > > From: AKASHI Takahiro > Sent: 29 June 2023 02:01 > To: Neil Jones > Cc: u-boot@lists.denx.de > Subject: Re: EFI Secure boot default keys > > On Wed, Jun 28, 2023 at 04:26:58PM +, Neil Jones wrote: > > Please can someone describe the format of the file needed for the default / > > built-in EFI secure boot keys (ubootefi.var) > > > > The only docs I have found suggest its best to enroll the keys from within > > u-boot onto some removable media, then copy this off and use this as the > > default, this is not very helpful and doesn't work for me: > > > > => fatload mmc 0:1 ${loadaddr} PK.aut > > 2053 bytes read in 18 ms (111.3 KiB/s) > > => setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize PK > > setenv - set environment variables > > > > Usage: > > setenv setenv [-f] name value ... > > - [forcibly] set environment variable 'name' to 'value ...' > > setenv [-f] name > > - [forcibly] delete environment variable 'name' > > > > my setenv doesn't support all the extra switches ? This is with 2022.04, > > all other EFI options seem to be in this release and I can boot unsigned > > EFI images ok. > > Please turn on CONFIG_CMD_NVEDIT_EFI when building your U-Boot. > > This option was disabled by the commit: > commit 3b728f8728fa (tag: efi-2020-01-rc1) > Author: Heinrich Schuchardt > Date: Sun Oct 6 15:44:22 2019 +0200 > > cmd: disable CMD_NVEDIT_EFI by default > > The binary size of efi has grown much since in the past, though. > > -Takahiro Akashi > > > Cheers, > > > > Neil > > > > > >
Re: EFI Secure boot default keys
On Thu, Jul 06, 2023 at 08:23:06AM +, Neil Jones wrote: > >> >> Please can someone describe the format of the file needed for the > >> >> default / built-in EFI secure boot keys (ubootefi.var) > >> >> > >> >> The only docs I have found suggest its best to enroll the keys from > >> >> within u-boot onto some removable media, then copy this off and use > >> >> this as the default, this is not very helpful and doesn't work for me: > >> >> > >> >> => fatload mmc 0:1 ${loadaddr} PK.aut > >> >> 2053 bytes read in 18 ms (111.3 KiB/s) > >> >> => setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize PK > >> >> setenv - set environment variables > >> >> > >> >> Usage: > >> >> setenv setenv [-f] name value ... > >> >> - [forcibly] set environment variable 'name' to 'value ...' > >> >> setenv [-f] name > >> >> - [forcibly] delete environment variable 'name' > >> >> > >> >> my setenv doesn't support all the extra switches ? This is with > >> >> 2022.04, all other EFI options seem to be in this release and I can > >> >> boot unsigned EFI images ok. > >> > > >> >Please turn on CONFIG_CMD_NVEDIT_EFI when building your U-Boot. > >> > > >> >This option was disabled by the commit: > >> > commit 3b728f8728fa (tag: efi-2020-01-rc1) > >> > Author: Heinrich Schuchardt > >> > Date: Sun Oct 6 15:44:22 2019 +0200 > >> > > >> > cmd: disable CMD_NVEDIT_EFI by default > >> > > >> >The binary size of efi has grown much since in the past, though. > >> > > >> >-Takahiro Akashi > >> > >> Thanks, I have secure boot working now. A tool to generate the > >> ubootefi.var offline or even just a description of the file format would > >> be very useful. > > > >Thank you for the suggestion. While I'd like to defer to Heinrich, > >the C definition of the file format can be found as struct efi_var_file > >in include/efi_variable.h > > > > Thanks! > > >> I have noticed one issue when using ubootefi.var on mmc, when I switch > >> boot order it wipes out the keys and I have to re-enrol them: > >> > >> => fatls mmc 0:1 > >> 3040 ubootefi.var > >> > >> 1 file(s), 0 dir(s) > > > >I'm not sure that secure boot related variables have been loaded > >at this point. > > This is during initial generation / enrollment of the variables > > >Anyhow, please try to enable CONFIG_EFI_VARIABLES_PRESEED with > >EFI_VAR_FILE_NAME set. Otherwise, those variables will never be > >restored. > >(This is another topic that are not described in doc/develop/uefi.) > > I have CONFIG_EFI_VARIABLES_PRESEED working, but while generating the file > ubootefi.var for the first time (without CONFIG_EFI_VARIABLES_PRESEED set) > you have to follow a specific order, or the file gets overwritten eg: > > Working: > > efidebug boot order 1 2 > efidebug boot add -b 1 Signed mmc 0:1 /ImageSig.efi > efidebug boot add -b 2 UnSigned mmc 0:1 /Image > fatload mmc 0:1 ${loadaddr} PK.aut > setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize PK > fatload mmc 0:1 ${loadaddr} KEK.aut > setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize KEK > fatload mmc 0:1 ${loadaddr} DB.aut > setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize db > > > Failing: > > setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize PK > fatload mmc 0:1 ${loadaddr} KEK.aut > setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize KEK > fatload mmc 0:1 ${loadaddr} DB.aut > setenv -e -nv -bs -rt -at -i ${loadaddr}:$filesize db > efidebug boot order 1 2 ### This command overwrites the keys just loaded Are you sure that "env print -e" shows all the variables including PK, KEK and db at this point? Since I don't have enough time to examine this issue, can you please try to trace efi_var_collect() in efi_var_file.c which is responsible for enumerating all the non-volatile variables to be saved at each SET_VARIABLE api call? -Takahiro Akashi > Cheers, > > Neil > > > > >Thanks, > >-Takahiro Akashi > > > >> => efidebug boot order 2 1 > >> => fatls mmc 0:1 > >> 440 ubootefi.var > >> > >> (Size drops fro
Re: [PATCH 0/4] introduce EFI_RAM_DISK_PROTOCOL
On Fri, Jul 07, 2023 at 01:00:40PM +0900, Masahisa Kojima wrote: > This series introduces the EFI_RAM_DISK_PROTOCOL implementation. > The major purpose of this series is a preparation for EFI HTTP(S) boot. > > Now U-Boot can download the distro installer ISO image > via wget or tftpboot commands, but U-Boot can not mount > the downloaded ISO image. > By calling EFI_RAM_DISK_PROTOCOL->register API, user can > mount the ISO image and boot the distro installer. > > Note that the installation process may not proceed > after the distro installer calls ExitBootServices() > since there is no hand-off process for the block device of > memory mapped ISO image. > > The EFI_RAM_DISK_PROTOCOL was tested with the > debian network installer[1] on qemu_arm64 platform. > The example procedure is as follows. > => tftpboot 4100 mini.iso > => efidebug disk load 4100 $filesize Can a disk created here be used natively on U-Boot with commands like (fs)ls or (fs)load? If so, it would be nice to mention the fact. -Takahiro Akashi > After these commands, ISO image is mounted like: > > => efidebug dh > > 7eec5910 (efiblk#0) > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0) > Block IO > > 7eec6140 (efiblk#0:1) > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0)/HD(1,0x01,0,0x0,0x33800) > Block IO > > 7eec62b0 (efiblk#0:2) > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0)/HD(2,0x01,0,0x33800,0x1) > Block IO > System Partition > Simple File System > > => dm tree > > blk 0 [ + ] efi_blk `-- efiblk#0 > partition 0 [ + ] blk_partition |-- efiblk#0:1 > partition 1 [ + ] blk_partition `-- efiblk#0:2 > > Debian can be successfully installed with this RAM disk on QEMU. > > [TODO] > - udevices created in ./lib/efi_driver/efi_block_device.c::efi_bl_bind() > are not removed when the efi_handle is removed. > So after unload the RAM disk, udevices still exist. > I plan to add a udevice removal process in > ./lib/efi_driver/efi_uclass.c::efi_uc_stop(). > In addition, I also plan to add unbind() callback in struct efi_driver_ops. > > > [1] > https://deb.debian.org/debian/dists/bookworm/main/installer-arm64/current/images/netboot/mini.iso > > Masahisa Kojima (4): > efi_loader: add RAM disk device path > efi_loader: add EFI_RAM_DISK_PROTOCOL implementation > cmd: efidebug: add RAM disk mount command > efi_selftest: add EFI_RAM_DISK_PROTOCOL selftest > > cmd/efidebug.c | 117 ++ > include/efi_api.h| 32 ++ > include/efi_loader.h | 4 + > lib/efi_driver/efi_uclass.c | 7 +- > lib/efi_loader/Kconfig | 6 + > lib/efi_loader/Makefile | 1 + > lib/efi_loader/efi_device_path_to_text.c | 14 + > lib/efi_loader/efi_ram_disk.c| 334 +++ > lib/efi_loader/efi_setup.c | 6 + > lib/efi_selftest/Makefile| 1 + > lib/efi_selftest/efi_selftest_ram_disk.c | 511 +++ > lib/uuid.c | 4 + > 12 files changed, 1035 insertions(+), 2 deletions(-) > create mode 100644 lib/efi_loader/efi_ram_disk.c > create mode 100644 lib/efi_selftest/efi_selftest_ram_disk.c > > > base-commit: e2e2aea5733f0d23cd9593bbefe5c803c552dcb9 > -- > 2.34.1 >
Re: [PATCH 0/4] introduce EFI_RAM_DISK_PROTOCOL
On Fri, Jul 07, 2023 at 08:29:12AM +0200, Heinrich Schuchardt wrote: > On 7/7/23 06:00, Masahisa Kojima wrote: > > This series introduces the EFI_RAM_DISK_PROTOCOL implementation. > > The major purpose of this series is a preparation for EFI HTTP(S) boot. > > > > Now U-Boot can download the distro installer ISO image > > via wget or tftpboot commands, but U-Boot can not mount > > the downloaded ISO image. > > By calling EFI_RAM_DISK_PROTOCOL->register API, user can > > mount the ISO image and boot the distro installer. > > If I understand you correctly, with your design RAM disks will only > exist in the EFI sub-system. Probably, not. As Kojima-san's "dm tree" shows, there is a U-Boot block device (and associated partition devices) thanks to your efi_driver framework. > We strive to synchronize what is happening on the driver model level and > on the UEFI level. I would prefer a design where we have a UCLASS_BLK > driver ram disks and the EFI_RAM_DISK_PROTOCOL is a one method of > managing ram disk devices. That said, I agree to starting with U-Boot block device implementation, UEFI_DISK comes automatically. It benefits both U-Boot proper and UEFI subsystem equally as well. (That is also what I meant to say in my first response.) > A big issue we have is RAM management. malloc() can only assign limited > amount of memory which is probably too small for the RAM disk you are > looking at. We manage page sized memory in the EFI sub-system but this > is not integrated with the LMB memory checks. Not sure, is it enough simply to add some restrictions on the start size and the size when a memory region is specified for a raw disk? -Takahiro Akashi > The necessary sequence of development is probably: > > * Rework memory management > * Implement ramdisks as UCLASS_BLK driver > * Implement the EFI_RAM_DISK_PROTOCOL based on the UCLASS_BLK driver. > > Best regards > > Heinrich > > > > > Note that the installation process may not proceed > > after the distro installer calls ExitBootServices() > > since there is no hand-off process for the block device of > > memory mapped ISO image. > > > > The EFI_RAM_DISK_PROTOCOL was tested with the > > debian network installer[1] on qemu_arm64 platform. > > The example procedure is as follows. > > => tftpboot 4100 mini.iso > > => efidebug disk load 4100 $filesize > > > > After these commands, ISO image is mounted like: > > > > => efidebug dh > > > > 7eec5910 (efiblk#0) > > > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0) > >Block IO > > > > 7eec6140 (efiblk#0:1) > > > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0)/HD(1,0x01,0,0x0,0x33800) > >Block IO > > > > 7eec62b0 (efiblk#0:2) > > > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0)/HD(2,0x01,0,0x33800,0x1) > >Block IO > >System Partition > >Simple File System > > > >=> dm tree > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > partition 0 [ + ] blk_partition |-- efiblk#0:1 > > partition 1 [ + ] blk_partition `-- efiblk#0:2 > > > > Debian can be successfully installed with this RAM disk on QEMU. > > > > [TODO] > > - udevices created in ./lib/efi_driver/efi_block_device.c::efi_bl_bind() > >are not removed when the efi_handle is removed. > >So after unload the RAM disk, udevices still exist. > >I plan to add a udevice removal process in > > ./lib/efi_driver/efi_uclass.c::efi_uc_stop(). > >In addition, I also plan to add unbind() callback in struct > > efi_driver_ops. > > > > > > [1] > > https://deb.debian.org/debian/dists/bookworm/main/installer-arm64/current/images/netboot/mini.iso > > > > Masahisa Kojima (4): > >efi_loader: add RAM disk device path > >efi_loader: add EFI_RAM_DISK_PROTOCOL implementation > >cmd: efidebug: add RAM disk mount command > >efi_selftest: add EFI_RAM_DISK_PROTOCOL selftest > > > > cmd/efidebug.c | 117 ++ > > include/efi_api.h| 32 ++ > > include/efi_loader.h | 4 + > > lib/efi_driver/efi_uclass.c | 7 +- > > lib/efi_loader/Kconfig | 6 + > > lib/efi_loader/Makefile | 1 + > > lib/efi_loader/efi_device_path_to_text.c | 14 + > > lib/efi_loader/efi_ram_disk.c| 334 +++ > > lib/efi_loader/efi_setup.c | 6 + > > lib/efi_selftest/Makefile| 1 + > > lib/efi_selftest/efi_selftest_ram_disk.c | 511 +++ > > lib/uuid.c | 4 + > > 12 files changed, 1035 insertions(+), 2 deletions(-) > > create mode 100644 lib/efi_loader/efi_ram_disk.c > > create mode 100644 lib/efi_selftest/efi_selftest_ram_disk.c > > > > > > base-commit: e2
Re: [PATCH 0/4] introduce EFI_RAM_DISK_PROTOCOL
On Fri, Jul 07, 2023 at 05:19:33PM +0900, Masahisa Kojima wrote: > Hi Akashi-san, > > On Fri, 7 Jul 2023 at 16:16, AKASHI Takahiro > wrote: > > > > On Fri, Jul 07, 2023 at 08:29:12AM +0200, Heinrich Schuchardt wrote: > > > On 7/7/23 06:00, Masahisa Kojima wrote: > > > > This series introduces the EFI_RAM_DISK_PROTOCOL implementation. > > > > The major purpose of this series is a preparation for EFI HTTP(S) boot. > > > > > > > > Now U-Boot can download the distro installer ISO image > > > > via wget or tftpboot commands, but U-Boot can not mount > > > > the downloaded ISO image. > > > > By calling EFI_RAM_DISK_PROTOCOL->register API, user can > > > > mount the ISO image and boot the distro installer. > > > > > > If I understand you correctly, with your design RAM disks will only > > > exist in the EFI sub-system. > > > > Probably, not. As Kojima-san's "dm tree" shows, there is a U-Boot > > block device (and associated partition devices) thanks to your > > efi_driver framework. > > Read/Write the RAM disk is expected to be called from the EFI context, so An associated U-Boot block device should work as well on top of your RAW_DISK_PROTOCOL via a generated RAM disk object (efi_disk). That is why SYMPLE_FILE_SYSTEM_PROTOCOL, which solely relies on U-Boot's proper filesystem subsystem, is installed to the RAM disk object. > native U-Boot can not access the RAM disk. I believe that, in theory, "fatls efidisk 0 1" (or efi_disk as an interface?) should work even under your current implementation. -Takahiro Akashi > # Honestly speaking, I'm not sure how U-Boot prohibits the access to > the EFI RAM disk > because the udevices are created for the RAM disk. > > Thanks, > Masahisa Kojima > > > > > > We strive to synchronize what is happening on the driver model level and > > > on the UEFI level. I would prefer a design where we have a UCLASS_BLK > > > driver ram disks and the EFI_RAM_DISK_PROTOCOL is a one method of > > > managing ram disk devices. > > > > That said, I agree to starting with U-Boot block device implementation, > > UEFI_DISK comes automatically. It benefits both U-Boot proper and > > UEFI subsystem equally as well. > > (That is also what I meant to say in my first response.) > > > > > A big issue we have is RAM management. malloc() can only assign limited > > > amount of memory which is probably too small for the RAM disk you are > > > looking at. We manage page sized memory in the EFI sub-system but this > > > is not integrated with the LMB memory checks. > > > > Not sure, is it enough simply to add some restrictions on the start size > > and the size when a memory region is specified for a raw disk? > > > > -Takahiro Akashi > > > > > The necessary sequence of development is probably: > > > > > > * Rework memory management > > > * Implement ramdisks as UCLASS_BLK driver > > > * Implement the EFI_RAM_DISK_PROTOCOL based on the UCLASS_BLK driver. > > > > > > Best regards > > > > > > Heinrich > > > > > > > > > > > Note that the installation process may not proceed > > > > after the distro installer calls ExitBootServices() > > > > since there is no hand-off process for the block device of > > > > memory mapped ISO image. > > > > > > > > The EFI_RAM_DISK_PROTOCOL was tested with the > > > > debian network installer[1] on qemu_arm64 platform. > > > > The example procedure is as follows. > > > > => tftpboot 4100 mini.iso > > > > => efidebug disk load 4100 $filesize > > > > > > > > After these commands, ISO image is mounted like: > > > > > > > > => efidebug dh > > > > > > > > 7eec5910 (efiblk#0) > > > > > > > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0) > > > >Block IO > > > > > > > > 7eec6140 (efiblk#0:1) > > > > > > > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0)/HD(1,0x01,0,0x0,0x33800) > > > >Block IO > > > > > > > > 7eec62b0 (efiblk#0:2) > > > > > > > > /RamDisk(0x4100,4974afff,3d5abd30-4175-87ce-6d64-d2ade523c4bb,0x0)/HD(2,0x01,0,0x33800,0x1) > > > >Block IO > > > &
Re: [PATCH 08/10] cmd: add scmi command for SCMI firmware
On Fri, Jul 07, 2023 at 11:35:52AM -0600, Simon Glass wrote: > Hi, > > On Tue, 4 Jul 2023 at 02:26, AKASHI Takahiro > wrote: > > > > On Mon, Jul 03, 2023 at 02:30:54PM +0100, Simon Glass wrote: > > > Hi, > > > > > > On Mon, 3 Jul 2023 at 01:55, AKASHI Takahiro > > > wrote: > > > > > > > > On Thu, Jun 29, 2023 at 08:10:00PM +0100, Simon Glass wrote: > > > > > Hi AKASHI, > > > > > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > > > wrote: > > > > > > > > > > > > This command, "scmi", provides a command line interface to various > > > > > > SCMI > > > > > > protocols. It supports at least initially SCMI base protocol with > > > > > > the sub > > > > > > command, "base", and is intended mainly for debug purpose. > > > > > > > > > > > > Signed-off-by: AKASHI Takahiro > > > > > > --- > > > > > > cmd/Kconfig | 8 ++ > > > > > > cmd/Makefile | 1 + > > > > > > cmd/scmi.c | 373 > > > > > > +++ > > > > > > 3 files changed, 382 insertions(+) > > > > > > create mode 100644 cmd/scmi.c > > > > > > > > > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > > > > > index 02e54f1e50fe..065470a76295 100644 > > > > > > --- a/cmd/Kconfig > > > > > > +++ b/cmd/Kconfig > > > > > > @@ -2504,6 +2504,14 @@ 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 > > > > > > protocols, > > > > > > + including Base protocol. > > > > > > > > > > Please mention what is SCMI > > > > > > > > I will give a full spelling. > > > > > > > > > > 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 ..c97f77e97d95 > > > > > > --- /dev/null > > > > > > +++ b/cmd/scmi.c > > > > > > @@ -0,0 +1,373 @@ > > > > > > +// SPDX-License-Identifier: GPL-2.0+ > > > > > > +/* > > > > > > + * SCMI utility command > > > > > > + * > > > > > > + * Copyright (c) 2023 Linaro Limited > > > > > > + * Author: AKASHI Takahiro > > > > > > + */ > > > > > > + > > > > > > +#include > > > > > > +#include > > > > > > +#include > > > > > > +#include /* uclass_get_device */ > > > > > > > > > > Goes before linux/bitfield.h > > > > > > > > Can you tell me why? > > > > > > It is just a convention: > > > https://u-boot.readthedocs.io/en/latest/develop/codingstyle.html#include-files > > > > Okay. > &g
Re: [PATCH 07/10] test: dm: add SCMI base protocol test
On Fri, Jul 07, 2023 at 11:35:49AM -0600, Simon Glass wrote: > Hi, > > On Tue, 4 Jul 2023 at 03:35, AKASHI Takahiro > wrote: > > > > Hi Simon, > > > > On Mon, Jul 03, 2023 at 02:30:57PM +0100, Simon Glass wrote: > > > Hi, > > > > > > On Mon, 3 Jul 2023 at 01:57, AKASHI Takahiro > > > wrote: > > > > > > > > On Thu, Jun 29, 2023 at 08:09:58PM +0100, Simon Glass wrote: > > > > > Hi AKASHI, > > > > > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > > > wrote: > > > > > > > > > > > > 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 > > > > > > --- > > > > > > test/dm/scmi.c | 112 > > > > > > + > > > > > > 1 file changed, 112 insertions(+) > > > > > > > > > > > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > > > > > > index 881be3171b7c..563017bb63e0 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,115 @@ 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; > > > > > > + const struct scmi_base_ops *ops; > > > > > > + u32 version, num_agents, num_protocols, impl_version; > > > > > > + u32 attributes, agent_id; > > > > > > + char vendor[SCMI_BASE_NAME_LENGTH_MAX], > > > > > > +agent_name[SCMI_BASE_NAME_LENGTH_MAX]; > > > > > > + u8 *protocols; > > > > > > + int ret; > > > > > > + > > > > > > + /* preparation */ > > > > > > + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, > > > > > > "scmi", > > > > > > + &agent_dev)); > > > > > > + ut_assertnonnull(agent_dev); > > > > > > + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev)); > > > > > > + ut_assertnonnull(base = scmi_get_protocol(agent_dev, > > > > > > + > > > > > > SCMI_PROTOCOL_ID_BASE)); > > > > > > + ut_assertnonnull(ops = dev_get_driver_ops(base)); > > > > > > + > > > > > > + /* version */ > > > > > > + ret = (*ops->protocol_version)(base, &version); > > > > > > > > > > Can you add uclass helpers to call each of the methods? That is how it > > > > > is commonly done. You should not be calling ops->xxx directly here. > > > > > > > > Yes, I will add inline functions instead. > > > > > > I don't mean inline...see all the other uclasses which define a > > > > Okay, I will *real* functions. > > > > > function which is implemented in the uclass. It is confusing when one > > > uclass does something different. People might copy this style and then > > > the code base diverges. Did you not notice this when looking around > > > the source tree? > > > > But one concern came up in my mind. > > Contrary to ordinary "device controllers", there
Re: [PATCH 0/4] introduce EFI_RAM_DISK_PROTOCOL
On Mon, Jul 10, 2023 at 11:13:12AM +0900, Masahisa Kojima wrote: > On Fri, 7 Jul 2023 at 18:12, AKASHI Takahiro > wrote: > > > > On Fri, Jul 07, 2023 at 05:19:33PM +0900, Masahisa Kojima wrote: > > > Hi Akashi-san, > > > > > > On Fri, 7 Jul 2023 at 16:16, AKASHI Takahiro > > > wrote: > > > > > > > > On Fri, Jul 07, 2023 at 08:29:12AM +0200, Heinrich Schuchardt wrote: > > > > > On 7/7/23 06:00, Masahisa Kojima wrote: > > > > > > This series introduces the EFI_RAM_DISK_PROTOCOL implementation. > > > > > > The major purpose of this series is a preparation for EFI HTTP(S) > > > > > > boot. > > > > > > > > > > > > Now U-Boot can download the distro installer ISO image > > > > > > via wget or tftpboot commands, but U-Boot can not mount > > > > > > the downloaded ISO image. > > > > > > By calling EFI_RAM_DISK_PROTOCOL->register API, user can > > > > > > mount the ISO image and boot the distro installer. > > > > > > > > > > If I understand you correctly, with your design RAM disks will only > > > > > exist in the EFI sub-system. > > > > > > > > Probably, not. As Kojima-san's "dm tree" shows, there is a U-Boot > > > > block device (and associated partition devices) thanks to your > > > > efi_driver framework. > > > > > > Read/Write the RAM disk is expected to be called from the EFI context, so > > > > An associated U-Boot block device should work as well on top of your > > RAW_DISK_PROTOCOL via a generated RAM disk object (efi_disk). > > That is why SYMPLE_FILE_SYSTEM_PROTOCOL, which solely relies on U-Boot's > > proper > > filesystem subsystem, is installed to the RAM disk object. > > I now realize that my RAM_DISK_PROTOCOL implementation happens to work > thanks to the block cache. > When I disable CONFIG_BLOCK_CACHE and load some EFI application(it > does set 'app_gd') > before calling RAM_DISK_PROTOCOL service, RAM_DISK_PROTOCOL does not work. > ConnectController fails. > > > > > > native U-Boot can not access the RAM disk. > > > > I believe that, in theory, "fatls efidisk 0 1" (or efi_disk as an > > interface?) > > should work even under your current implementation. > > "fatls efiloader 0:2" does not work. > I think "efiloader" device is designed to be accessed from EFI application > only > even if it is listed by "dm tree". I don't believe so. (the interface name may be "efi_blk" or "efiblk", though.) If the command fails, it's a bug. Must be fixed. > I understand that ramdisk as UCLASS_BLK driver is required as Heinrich said. That said, I agree to starting with UCLASS_BLK from the viewpoint of U-Boot driver model/UEFI integration. -Takahiro Akashi > > Thanks, > Masahisa Kojima > > > > > -Takahiro Akashi > > > > > # Honestly speaking, I'm not sure how U-Boot prohibits the access to > > > the EFI RAM disk > > > because the udevices are created for the RAM disk. > > > > > > Thanks, > > > Masahisa Kojima > > > > > > > > > > > > We strive to synchronize what is happening on the driver model level > > > > > and > > > > > on the UEFI level. I would prefer a design where we have a UCLASS_BLK > > > > > driver ram disks and the EFI_RAM_DISK_PROTOCOL is a one method of > > > > > managing ram disk devices. > > > > > > > > That said, I agree to starting with U-Boot block device implementation, > > > > UEFI_DISK comes automatically. It benefits both U-Boot proper and > > > > UEFI subsystem equally as well. > > > > (That is also what I meant to say in my first response.) > > > > > > > > > A big issue we have is RAM management. malloc() can only assign > > > > > limited > > > > > amount of memory which is probably too small for the RAM disk you are > > > > > looking at. We manage page sized memory in the EFI sub-system but this > > > > > is not integrated with the LMB memory checks. > > > > > > > > Not sure, is it enough simply to add some restrictions on the start size > > > > and the size when a memory region is specified for a raw disk? > > > > > > > > -Takahiro Akashi > > > > > > > >
Re: [PATCH v1] mkeficapsule: fix efi_firmware_management_capsule_header data type
On Sun, Jul 09, 2023 at 10:31:55AM +0200, Heinrich Schuchardt wrote: > On 6/16/23 10:28, Stefan Herbrechtsmeier wrote: > > From: Malte Schmidt > > > > The data type of item_offset_list shall be UINT64 according to the UEFI [1] > > specifications. > > > > In include/efi_api.h the correct data type is used. The bug was probably > > never noticed because of little endianness. > > > > [1] https://uefi.org/specs/UEFI/2.10/index.html > > > > Signed-off-by: Malte Schmidt > > > > Signed-off-by: Stefan Herbrechtsmeier > > > > --- > > > > tools/eficapsule.h | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/tools/eficapsule.h b/tools/eficapsule.h > > index 753fb73313..2099a2e9b8 100644 > > --- a/tools/eficapsule.h > > +++ b/tools/eficapsule.h > > @@ -63,7 +63,7 @@ struct efi_firmware_management_capsule_header { > > uint32_t version; > > uint16_t embedded_driver_count; > > uint16_t payload_item_count; > > - uint32_t item_offset_list[]; > > + uint64_t item_offset_list[]; > > Defining the same structure in two places it bad practice. > https://source.denx.de/u-boot/custodians/u-boot-efi/-/issues/11 I had a good reason for adding a tool-specific header, instead of using headers under 'include' dir, when I posted v7 of "efi_loader: capsule: improve capsule authentication support" patch. The cover letter says, === v7 (Nov 16, 2021) ... * define eficapsule.h and include it from mkeficapsule (patch#3) Hopefully, the tool can now compile on non-linux host. === If I correctly remember, this reflects the comment below and the succeeding discussions: https://lists.denx.de/pipermail/u-boot/2021-November/465859.html -Takahiro Akashi > Reviewed-by: Heinrich Schuchardt > > > } __packed; > > > > /* image_capsule_support */ >
Re: [PATCH 07/10] test: dm: add SCMI base protocol test
Hi Simon, On Mon, Jul 10, 2023 at 01:45:58PM -0600, Simon Glass wrote: > Hi, > > On Sun, 9 Jul 2023 at 20:04, AKASHI Takahiro > wrote: > > > > On Fri, Jul 07, 2023 at 11:35:49AM -0600, Simon Glass wrote: > > > Hi, > > > > > > On Tue, 4 Jul 2023 at 03:35, AKASHI Takahiro > > > wrote: > > > > > > > > Hi Simon, > > > > > > > > On Mon, Jul 03, 2023 at 02:30:57PM +0100, Simon Glass wrote: > > > > > Hi, > > > > > > > > > > On Mon, 3 Jul 2023 at 01:57, AKASHI Takahiro > > > > > wrote: > > > > > > > > > > > > On Thu, Jun 29, 2023 at 08:09:58PM +0100, Simon Glass wrote: > > > > > > > Hi AKASHI, > > > > > > > > > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > > > > > wrote: > > > > > > > > > > > > > > > > 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 > > > > > > > > --- > > > > > > > > test/dm/scmi.c | 112 > > > > > > > > + > > > > > > > > 1 file changed, 112 insertions(+) > > > > > > > > > > > > > > > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > > > > > > > > index 881be3171b7c..563017bb63e0 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,115 @@ 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; > > > > > > > > + const struct scmi_base_ops *ops; > > > > > > > > + u32 version, num_agents, num_protocols, impl_version; > > > > > > > > + u32 attributes, agent_id; > > > > > > > > + char vendor[SCMI_BASE_NAME_LENGTH_MAX], > > > > > > > > +agent_name[SCMI_BASE_NAME_LENGTH_MAX]; > > > > > > > > + u8 *protocols; > > > > > > > > + int ret; > > > > > > > > + > > > > > > > > + /* preparation */ > > > > > > > > + > > > > > > > > ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", > > > > > > > > + &agent_dev)); > > > > > > > > + ut_assertnonnull(agent_dev); > > > > > > > > + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev)); > > > > > > > > + ut_assertnonnull(base = scmi_get_protocol(agent_dev, > > > > > > > > + > > > > > > > > SCMI_PROTOCOL_ID_BASE)); > > > > > > > > + ut_assertnonnull(ops = dev_get_driver_ops(base)); > > > > > > > > + > > > > > > > > + /* version */ > > > > > > > > +
Re: [PATCH 07/10] test: dm: add SCMI base protocol test
Hi Simon, On Tue, Jul 11, 2023 at 12:41:58PM -0600, Simon Glass wrote: > Hi Takahiro, > > On Mon, 10 Jul 2023 at 19:02, AKASHI Takahiro > wrote: > > > > Hi Simon, > > > > On Mon, Jul 10, 2023 at 01:45:58PM -0600, Simon Glass wrote: > > > Hi, > > > > > > On Sun, 9 Jul 2023 at 20:04, AKASHI Takahiro > > > wrote: > > > > > > > > On Fri, Jul 07, 2023 at 11:35:49AM -0600, Simon Glass wrote: > > > > > Hi, > > > > > > > > > > On Tue, 4 Jul 2023 at 03:35, AKASHI Takahiro > > > > > wrote: > > > > > > > > > > > > Hi Simon, > > > > > > > > > > > > On Mon, Jul 03, 2023 at 02:30:57PM +0100, Simon Glass wrote: > > > > > > > Hi, > > > > > > > > > > > > > > On Mon, 3 Jul 2023 at 01:57, AKASHI Takahiro > > > > > > > wrote: > > > > > > > > > > > > > > > > On Thu, Jun 29, 2023 at 08:09:58PM +0100, Simon Glass wrote: > > > > > > > > > Hi AKASHI, > > > > > > > > > > > > > > > > > > On Wed, 28 Jun 2023 at 01:49, AKASHI Takahiro > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > 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 > > > > > > > > > > --- > > > > > > > > > > test/dm/scmi.c | 112 > > > > > > > > > > + > > > > > > > > > > 1 file changed, 112 insertions(+) > > > > > > > > > > > > > > > > > > > > diff --git a/test/dm/scmi.c b/test/dm/scmi.c > > > > > > > > > > index 881be3171b7c..563017bb63e0 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,115 @@ 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; > > > > > > > > > > + const struct scmi_base_ops *ops; > > > > > > > > > > + 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; > > > > > > > > > > + > > > > > > &g
Reminder, Re: [PATCH] clk: scmi: claim the dependency on CONFIG_CLK
Hi Lukasz, Sean, Can you review this patch, please? -Takahiro Akashi On Mon, Jun 12, 2023 at 10:14:49AM +0900, AKASHI Takahiro wrote: > Without CONFIG_CLK, the build fails with the following message: > LD u-boot > aarch64-none-linux-gnu-ld.bfd: drivers/firmware/scmi/scmi_agent-uclass.o: \ > in function `scmi_bind_protocols': > .../drivers/firmware/scmi/scmi_agent-uclass.c:79: undefined reference to \ > `_u_boot_list_2_driver_2_scmi_clock' > > Signed-off-by: AKASHI Takahiro > --- > drivers/clk/Kconfig | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig > index 3ad5af964f3f..29859cdfa158 100644 > --- a/drivers/clk/Kconfig > +++ b/drivers/clk/Kconfig > @@ -160,6 +160,7 @@ config SANDBOX_CLK_CCF > > config CLK_SCMI > bool "Enable SCMI clock driver" > + depends on CLK > depends on SCMI_FIRMWARE > help > Enable this option if you want to support clock devices exposed > -- > 2.41.0 >
Re: [PATCH] firmware: scmi: return a right errno for SCMI status code
Hi Tom, Can you pick up this patch, please? It's an easy bugfix. -Takahiro Akashi On Tue, Jun 13, 2023 at 10:30:45AM +0900, AKASHI Takahiro wrote: > scmi_to_linux_errno() is set to return an appropriate errno > which corresponds to a given SCMI status code. > But the current implementation always returns the same value. > > Signed-off-by: AKASHI Takahiro > --- > drivers/firmware/scmi/scmi_agent-uclass.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c > b/drivers/firmware/scmi/scmi_agent-uclass.c > index 54d563d929b8..02de692d66f3 100644 > --- a/drivers/firmware/scmi/scmi_agent-uclass.c > +++ b/drivers/firmware/scmi/scmi_agent-uclass.c > @@ -46,7 +46,7 @@ int scmi_to_linux_errno(s32 scmi_code) > > for (n = 0; n < ARRAY_SIZE(scmi_linux_errmap); n++) > if (scmi_code == scmi_linux_errmap[n].scmi) > - return scmi_linux_errmap[1].errno; > + return scmi_linux_errmap[n].errno; > > return -EPROTO; > } > -- > 2.41.0 >
Re: [PATCH v1 1/2] drivers: firmware: introduce Meson Secure Monitor driver
On Tue, Jul 11, 2023 at 01:13:29PM -0600, Simon Glass wrote: > +AKASHI Takahiro Me? > Hi Alexey, > > On Tue, 11 Jul 2023 at 04:25, Alexey Romanov wrote: > > > > Hi Simon, > > > > On Mon, Jul 10, 2023 at 01:45:53PM -0600, Simon Glass wrote: > > > Hi Alexey, > > > > > > On Mon, 10 Jul 2023 at 02:34, Alexey Romanov > > > wrote: > > > > > > > > > > > > Hello! > > > > > > > > On Fri, Jul 07, 2023 at 11:35:47AM -0600, Simon Glass wrote: > > > > > Hi Alexey, > > > > > > > > > > On Fri, 7 Jul 2023 at 09:43, Alexey Romanov > > > > > wrote: > > > > > > > > > > > > Hello, Simon! > > > > > > > > > > > > On Thu, Jul 06, 2023 at 09:58:02AM -0600, Simon Glass wrote: > > > > > > > Hi Alexey, > > > > > > > > > > > > > > On Thu, 6 Jul 2023 at 14:16, Alexey Romanov > > > > > > > wrote: > > > > > > > > > > > > > > > > At the moment, only smc API is a set of functions in > > > > > > > > arch/arm/mach-meson/sm.c. This approach is hard to configure > > > > > > > > and also doesni't contain any generic API for calling smc. > > > > > > > > > > > > > > > > This patch add Meson SM driver with generic API (struct > > > > > > > > meson_sm_ops): > > > > > > > > > > > > > > > > - sm_call() > > > > > > > > - sm_call_write() > > > > > > > > - sm_call_read() > > > > > > > > > > > > > > > > A typical driver usage example is shown here: > > > > > > > > > > > > > > > > 1. uclass_get_device_by_driver(UCLASS_FIRMWARE, > > > > > > > > "secure-monitor", &dev); > > > > > > > > 2. handle = meson_sm_get_handle(dev); > > > > > > > > 3. handle->ops.sm_call(dev, cmd, ...); > > > > > > > > > > > > > > > > Signed-off-by: Alexey Romanov > > > > > > > > --- > > > > > > > > arch/arm/mach-meson/Kconfig | 1 + > > > > > > > > drivers/firmware/Kconfig | 10 ++ > > > > > > > > drivers/firmware/Makefile | 1 + > > > > > > > > drivers/firmware/meson/Kconfig| 6 + > > > > > > > > drivers/firmware/meson/Makefile | 3 + > > > > > > > > drivers/firmware/meson/meson_sm.c | 217 > > > > > > > > ++ > > > > > > > > include/meson/sm_handle.h | 38 ++ > > > > > > > > 7 files changed, 276 insertions(+) > > > > > > > > create mode 100644 drivers/firmware/meson/Kconfig > > > > > > > > create mode 100644 drivers/firmware/meson/Makefile > > > > > > > > create mode 100644 drivers/firmware/meson/meson_sm.c > > > > > > > > create mode 100644 include/meson/sm_handle.h > > > > > > > > > > > > > > Please can you use the remoteproc uclass for this and add a > > > > > > > proper driver? > > > > > > > > > > > > > > > > > > > I don't see it architecturally well. Can you explain please? > > > > > > > > > > > > This driver is just ARM SMC fw interface. There seems to be nothing > > > > > > to > > > > > > do here for remoteproc uclass. > > > > > > > > > > Well you seem to be implementing a remote CPU interface, which is what > > > > > remoteproc is for. How does Linux do this? > > > > > > > > The main idea of the patchset is to abstract the smc calls (which run on > > > > the same CPU) and make a request to the firmware that runs on a higher > > > > EL. UCLASS_REMOTEPROC may give the impression that we are > > > > interacting with another CPU, although this is not the case. > > > > > > > > Also, UCLASS_REMOTEPROC requires two mandatory interfaces: load() and > > > > start(), and I don't even know how to apply my current changes to them. > > > > > > You can return -ENOSYS i
[RFC] efi_driver: fix a parent issue in efi-created block devices
An EFI application may create an EFI block device (EFI_BLOCK_IO_PROTOCOL) in EFI world, which in turn generates a corresponding U-Boot block device based on U-Boot's Driver Model. The latter device, however, doesn't work as U-Boot proper block device due to an issue in efi_driver's implementation. We saw discussions in the past, most recently in [1]. [1] https://lists.denx.de/pipermail/u-boot/2023-July/522565.html This RFC patch tries to address (part of) the issue. If it is considered acceptable, I will create a formal patch. Withtout this patch, ===8<=== => env set efi_selftest 'block device' => bootefi selftest ... Summary: 0 failures => dm tree Class Index Probed DriverName --- root 0 [ + ] root_driver root_driver ... bootmeth 7 [ ] vbe_simple| `-- vbe_simple blk 0 [ + ] efi_blk `-- efiblk#0 partition 0 [ + ] blk_partition `-- efiblk#0:1 => ls efiloader 0:1 ** Bad device specification efiloader 0 ** Couldn't find partition efiloader 0:1 ===>8=== With this patch applied, efiblk#0(:1) now gets accessible. ===8<=== => env set efi_selftest 'block device' => bootefi selftest ... Summary: 0 failures => dm tree Class Index Probed DriverName --- root 0 [ + ] root_driver root_driver ... bootmeth 7 [ ] vbe_simple| `-- vbe_simple efi 0 [ + ] EFI block driver `-- /VenHw(dbca4c98-6cb0-694d-0872-819c650cb7b8) blk 0 [ + ] efi_blk `-- efiblk#0 partition 0 [ + ] blk_partition `-- efiblk#0:1 => ls efiloader 0:1 13 hello.txt 7 u-boot.txt 2 file(s), 0 dir(s) ===>8=== Signed-off-by: AKASHI Takahiro --- include/efi_driver.h | 2 +- lib/efi_driver/efi_block_device.c| 17 - lib/efi_driver/efi_uclass.c | 8 +++- lib/efi_selftest/efi_selftest_block_device.c | 2 ++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/efi_driver.h b/include/efi_driver.h index 63a95e4cf800..ed66796f3519 100644 --- a/include/efi_driver.h +++ b/include/efi_driver.h @@ -42,7 +42,7 @@ struct efi_driver_ops { const efi_guid_t *child_protocol; efi_status_t (*init)(struct efi_driver_binding_extended_protocol *this); efi_status_t (*bind)(struct efi_driver_binding_extended_protocol *this, -efi_handle_t handle, void *interface); +efi_handle_t handle, void *interface, char *name); }; #endif /* _EFI_DRIVER_H */ diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index add00eeebbea..43b7ed7c973c 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -115,9 +115,9 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, * Return: status code */ static efi_status_t -efi_bl_create_block_device(efi_handle_t handle, void *interface) +efi_bl_create_block_device(efi_handle_t handle, void *interface, struct udevice *parent) { - struct udevice *bdev = NULL, *parent = dm_root(); + struct udevice *bdev = NULL; efi_status_t ret; int devnum; char *name; @@ -181,7 +181,7 @@ err: */ static efi_status_t efi_bl_bind( struct efi_driver_binding_extended_protocol *this, - efi_handle_t handle, void *interface) + efi_handle_t handle, void *interface, char *name) { efi_status_t ret = EFI_SUCCESS; struct efi_object *obj = efi_search_obj(handle); @@ -191,8 +191,15 @@ static efi_status_t efi_bl_bind( if (!obj || !interface) return EFI_INVALID_PARAMETER; - if (!handle->dev) - ret = efi_bl_create_block_device(handle, interface); + if (!handle->dev) { + struct udevice *parent; + + ret = device_bind_driver(dm_root(), "EFI block driver", name, &parent); + if (!ret) + ret = efi_bl_create_block_device(handle, interface, parent); + else + ret = EFI_DEVICE_ERROR; + } return ret; } diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index 45f935198874..bf669742783e 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -145,7 +145,13 @@ static efi_status_t EFIAPI efi_uc_start( ret = check_node_type(controller_handle); if (ret != EFI_SUCCESS) goto err; - ret = bp->ops->bind(bp, controller_handle, interface); + + struct efi_handle
Re: [RFC] efi_driver: fix a parent issue in efi-created block devices
Hi Simon, On Tue, Jul 18, 2023 at 07:08:45PM -0600, Simon Glass wrote: > Hi AKASHI, > > On Tue, 18 Jul 2023 at 18:22, AKASHI Takahiro > wrote: > > > > An EFI application may create an EFI block device (EFI_BLOCK_IO_PROTOCOL) in > > EFI world, which in turn generates a corresponding U-Boot block device > > based on > > U-Boot's Driver Model. > > The latter device, however, doesn't work as U-Boot proper block device > > due to an issue in efi_driver's implementation. We saw discussions in the > > past, > > most recently in [1]. > > > > [1] https://lists.denx.de/pipermail/u-boot/2023-July/522565.html > > > > This RFC patch tries to address (part of) the issue. > > If it is considered acceptable, I will create a formal patch. > > > > Withtout this patch, > > ===8<=== > > => env set efi_selftest 'block device' > > => bootefi selftest > > ... > > > > Summary: 0 failures > > > > => dm tree > > Class Index Probed DriverName > > --- > > root 0 [ + ] root_driver root_driver > > ... > > bootmeth 7 [ ] vbe_simple| `-- vbe_simple > > blk 0 [ + ] efi_blk `-- efiblk#0 > > partition 0 [ + ] blk_partition `-- efiblk#0:1 > > => ls efiloader 0:1 > > ** Bad device specification efiloader 0 ** > > Couldn't find partition efiloader 0:1 > > ===>8=== > > > > With this patch applied, efiblk#0(:1) now gets accessible. > > > > ===8<=== > > => env set efi_selftest 'block device' > > => bootefi selftest > > ... > > > > Summary: 0 failures > > > > => dm tree > > Class Index Probed DriverName > > --- > > root 0 [ + ] root_driver root_driver > > ... > > bootmeth 7 [ ] vbe_simple| `-- vbe_simple > > efi 0 [ + ] EFI block driver `-- > > /VenHw(dbca4c98-6cb0-694d-0872-819c650cb7b8) > > blk 0 [ + ] efi_blk `-- efiblk#0 > > partition 0 [ + ] blk_partition `-- efiblk#0:1 > > => ls efiloader 0:1 > >13 hello.txt > > 7 u-boot.txt > > > > 2 file(s), 0 dir(s) > > ===>8=== > > > > Signed-off-by: AKASHI Takahiro > > --- > > include/efi_driver.h | 2 +- > > lib/efi_driver/efi_block_device.c| 17 - > > lib/efi_driver/efi_uclass.c | 8 +++- > > lib/efi_selftest/efi_selftest_block_device.c | 2 ++ > > 4 files changed, 22 insertions(+), 7 deletions(-) > > > > diff --git a/include/efi_driver.h b/include/efi_driver.h > > index 63a95e4cf800..ed66796f3519 100644 > > --- a/include/efi_driver.h > > +++ b/include/efi_driver.h > > @@ -42,7 +42,7 @@ struct efi_driver_ops { > > const efi_guid_t *child_protocol; > > efi_status_t (*init)(struct efi_driver_binding_extended_protocol > > *this); > > efi_status_t (*bind)(struct efi_driver_binding_extended_protocol > > *this, > > -efi_handle_t handle, void *interface); > > +efi_handle_t handle, void *interface, char > > *name); > > }; > > > > #endif /* _EFI_DRIVER_H */ > > diff --git a/lib/efi_driver/efi_block_device.c > > b/lib/efi_driver/efi_block_device.c > > index add00eeebbea..43b7ed7c973c 100644 > > --- a/lib/efi_driver/efi_block_device.c > > +++ b/lib/efi_driver/efi_block_device.c > > @@ -115,9 +115,9 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t > > blknr, lbaint_t blkcnt, > > * Return: status code > > */ > > static efi_status_t > > -efi_bl_create_block_device(efi_handle_t handle, void *interface) > > +efi_bl_create_block_device(efi_handle_t handle, void *interface, struct > > udevice *parent) > > { > > - struct udevice *bdev = NULL, *parent = dm_root(); > > + struct udevice *bdev = NULL; > > efi_status_t ret; > > int devnum; > > char *name; > > @@ -181,7 +181,7 @@ err: > > */ > > static efi_status_t efi_bl_bind( > > struct efi_driver_binding_extended_protocol *this, > > - efi_handle_t handle, void *int
Re: [PATCH 1/1] efi_loader: support all uclasses in device path
On Wed, Jul 19, 2023 at 06:43:08AM +0200, Heinrich Schuchardt wrote: > On devices with multiple USB mass storage devices errors like > > Path /../USB(0x0,0x0)/USB(0x1,0x0)/Ctrl(0x0) > already installed. > > are seen. This is due to creating non-unique device paths. To uniquely > identify devices we must provide path nodes for all devices on the path > from the root device. > > Add support for generating device path nodes for all uclasses. I think that this is the last resort for devices that cannot be classified/ identified by any other means. If possible, should we provide a more concrete device path? I have submitted a patch specifically for USB devices in the past: https://lists.denx.de/pipermail/u-boot/2021-November/468216.html # I'm no longer working on this patch, though. -Takahiro Akashi > Reported-by: Suniel Mahesh > Signed-off-by: Heinrich Schuchardt > --- > include/efi_api.h| 7 > lib/efi_loader/efi_device_path.c | 56 ++-- > 2 files changed, 32 insertions(+), 31 deletions(-) > > diff --git a/include/efi_api.h b/include/efi_api.h > index 55a4c989fc..8f5ef5f680 100644 > --- a/include/efi_api.h > +++ b/include/efi_api.h > @@ -579,6 +579,13 @@ struct efi_device_path_vendor { > u8 vendor_data[]; > } __packed; > > +struct efi_device_path_udevice { > + struct efi_device_path dp; > + efi_guid_t guid; > + int uclass_id; > + int dev_number; > +} __packed; > + > struct efi_device_path_controller { > struct efi_device_path dp; > u32 controller_number; > diff --git a/lib/efi_loader/efi_device_path.c > b/lib/efi_loader/efi_device_path.c > index 04ebb449ca..d0be869d94 100644 > --- a/lib/efi_loader/efi_device_path.c > +++ b/lib/efi_loader/efi_device_path.c > @@ -10,6 +10,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -38,16 +39,6 @@ const struct efi_device_path END = { > .length = sizeof(END), > }; > > -/* template ROOT node: */ > -static const struct efi_device_path_vendor ROOT = { > - .dp = { > - .type = DEVICE_PATH_TYPE_HARDWARE_DEVICE, > - .sub_type = DEVICE_PATH_SUB_TYPE_VENDOR, > - .length = sizeof(ROOT), > - }, > - .guid = U_BOOT_GUID, > -}; > - > #if defined(CONFIG_MMC) > /* > * Determine if an MMC device is an SD card. > @@ -497,13 +488,12 @@ bool efi_dp_is_multi_instance(const struct > efi_device_path *dp) > __maybe_unused static unsigned int dp_size(struct udevice *dev) > { > if (!dev || !dev->driver) > - return sizeof(ROOT); > + return sizeof(struct efi_device_path_udevice); > > switch (device_get_uclass_id(dev)) { > case UCLASS_ROOT: > - case UCLASS_SIMPLE_BUS: > /* stop traversing parents at this point: */ > - return sizeof(ROOT); > + return sizeof(struct efi_device_path_udevice); > case UCLASS_ETH: > return dp_size(dev->parent) + > sizeof(struct efi_device_path_mac_addr); > @@ -582,8 +572,8 @@ __maybe_unused static unsigned int dp_size(struct udevice > *dev) > return dp_size(dev->parent) + > sizeof(struct efi_device_path_usb); > default: > - /* just skip over unknown classes: */ > - return dp_size(dev->parent); > + return dp_size(dev->parent) + > + sizeof(struct efi_device_path_udevice); > } > } > > @@ -600,13 +590,6 @@ __maybe_unused static void *dp_fill(void *buf, struct > udevice *dev) > return buf; > > switch (device_get_uclass_id(dev)) { > - case UCLASS_ROOT: > - case UCLASS_SIMPLE_BUS: { > - /* stop traversing parents at this point: */ > - struct efi_device_path_vendor *vdp = buf; > - *vdp = ROOT; > - return &vdp[1]; > - } > #ifdef CONFIG_NETDEVICES > case UCLASS_ETH: { > struct efi_device_path_mac_addr *dp = > @@ -811,11 +794,24 @@ __maybe_unused static void *dp_fill(void *buf, struct > udevice *dev) > > return &udp[1]; > } > - default: > - /* If the uclass driver is missing, this will show NULL */ > - log_debug("unhandled device class: %s (%s)\n", dev->name, > - dev_get_uclass_name(dev)); > - return dp_fill(buf, dev->parent); > + default: { > + struct efi_device_path_udevice *vdp; > + enum uclass_id uclass_id = device_get_uclass_id(dev); > + > + if (uclass_id == UCLASS_ROOT) > + vdp = buf; > + else > + vdp = dp_fill(buf, dev->parent); > + > + vdp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; > + vdp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; > + vdp->dp.length = sizeof(*vdp); > + memcpy(&vdp->guid, &efi_
Re: [RFC] efi_driver: fix a parent issue in efi-created block devices
On Wed, Jul 19, 2023 at 03:15:10PM +0200, Heinrich Schuchardt wrote: > On 19.07.23 15:04, Simon Glass wrote: > > Hi, > > > > On Tue, 18 Jul 2023 at 19:54, AKASHI Takahiro > > wrote: > > > > > > Hi Simon, > > > > > > On Tue, Jul 18, 2023 at 07:08:45PM -0600, Simon Glass wrote: > > > > Hi AKASHI, > > > > > > > > On Tue, 18 Jul 2023 at 18:22, AKASHI Takahiro > > > > wrote: > > > > > > > > > > An EFI application may create an EFI block device > > > > > (EFI_BLOCK_IO_PROTOCOL) in > > > > > EFI world, which in turn generates a corresponding U-Boot block > > > > > device based on > > > > > U-Boot's Driver Model. > > > > > The latter device, however, doesn't work as U-Boot proper block device > > > > > due to an issue in efi_driver's implementation. We saw discussions in > > > > > the past, > > > > > most recently in [1]. > > > > > > > > > >[1] https://lists.denx.de/pipermail/u-boot/2023-July/522565.html > > > > > > > > > > This RFC patch tries to address (part of) the issue. > > > > > If it is considered acceptable, I will create a formal patch. > > > > > > > > > > Withtout this patch, > > > > > ===8<=== > > > > > => env set efi_selftest 'block device' > > > > > => bootefi selftest > > > > > ... > > > > > > > > > > Summary: 0 failures > > > > > > > > > > => dm tree > > > > > Class Index Probed DriverName > > > > > --- > > > > > root 0 [ + ] root_driver root_driver > > > > > ... > > > > > bootmeth 7 [ ] vbe_simple| `-- vbe_simple > > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > > > > partition 0 [ + ] blk_partition `-- efiblk#0:1 > > > > > => ls efiloader 0:1 > > > > > ** Bad device specification efiloader 0 ** > > > > > Couldn't find partition efiloader 0:1 > > > > > ===>8=== > > > > > > > > > > With this patch applied, efiblk#0(:1) now gets accessible. > > > > > > > > > > ===8<=== > > > > > => env set efi_selftest 'block device' > > > > > => bootefi selftest > > > > > ... > > > > > > > > > > Summary: 0 failures > > > > > > > > > > => dm tree > > > > > Class Index Probed DriverName > > > > > --- > > > > > root 0 [ + ] root_driver root_driver > > > > > ... > > > > > bootmeth 7 [ ] vbe_simple| `-- vbe_simple > > > > > efi 0 [ + ] EFI block driver `-- > > > > > /VenHw(dbca4c98-6cb0-694d-0872-819c650cb7b8) > > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > > > > partition 0 [ + ] blk_partition `-- > > > > > efiblk#0:1 > > > > > => ls efiloader 0:1 > > > > > 13 hello.txt > > > > > 7 u-boot.txt > > > > > > > > > > 2 file(s), 0 dir(s) > > > > > ===>8=== > > > > > > > > > > Signed-off-by: AKASHI Takahiro > > > > > --- > > > > > include/efi_driver.h | 2 +- > > > > > lib/efi_driver/efi_block_device.c| 17 - > > > > > lib/efi_driver/efi_uclass.c | 8 +++- > > > > > lib/efi_selftest/efi_selftest_block_device.c | 2 ++ > > > > > 4 files changed, 22 insertions(+), 7 deletions(-) > > > > > > > > > > diff --git a/include/efi_driver.h b/include/efi_driver.h > > > > > index 63a95e4cf800..ed66796f3519 100644 > > > > > --- a/include/efi_driver.h > > > > > +++ b/include/efi_driver.h > > > > > @@ -42,7 +42,7 @@ struct efi_driver_ops { > > > > > const efi_guid_t *child_protocol; &g
Re: [RFC] efi_driver: fix a parent issue in efi-created block devices
Hi Simon, On Wed, Jul 19, 2023 at 07:04:06AM -0600, Simon Glass wrote: > Hi, > > On Tue, 18 Jul 2023 at 19:54, AKASHI Takahiro > wrote: > > > > Hi Simon, > > > > On Tue, Jul 18, 2023 at 07:08:45PM -0600, Simon Glass wrote: > > > Hi AKASHI, > > > > > > On Tue, 18 Jul 2023 at 18:22, AKASHI Takahiro > > > wrote: > > > > > > > > An EFI application may create an EFI block device > > > > (EFI_BLOCK_IO_PROTOCOL) in > > > > EFI world, which in turn generates a corresponding U-Boot block device > > > > based on > > > > U-Boot's Driver Model. > > > > The latter device, however, doesn't work as U-Boot proper block device > > > > due to an issue in efi_driver's implementation. We saw discussions in > > > > the past, > > > > most recently in [1]. > > > > > > > > [1] https://lists.denx.de/pipermail/u-boot/2023-July/522565.html > > > > > > > > This RFC patch tries to address (part of) the issue. > > > > If it is considered acceptable, I will create a formal patch. > > > > > > > > Withtout this patch, > > > > ===8<=== > > > > => env set efi_selftest 'block device' > > > > => bootefi selftest > > > > ... > > > > > > > > Summary: 0 failures > > > > > > > > => dm tree > > > > Class Index Probed DriverName > > > > --- > > > > root 0 [ + ] root_driver root_driver > > > > ... > > > > bootmeth 7 [ ] vbe_simple| `-- vbe_simple > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > > > partition 0 [ + ] blk_partition `-- efiblk#0:1 > > > > => ls efiloader 0:1 > > > > ** Bad device specification efiloader 0 ** > > > > Couldn't find partition efiloader 0:1 > > > > ===>8=== > > > > > > > > With this patch applied, efiblk#0(:1) now gets accessible. > > > > > > > > ===8<=== > > > > => env set efi_selftest 'block device' > > > > => bootefi selftest > > > > ... > > > > > > > > Summary: 0 failures > > > > > > > > => dm tree > > > > Class Index Probed DriverName > > > > --- > > > > root 0 [ + ] root_driver root_driver > > > > ... > > > > bootmeth 7 [ ] vbe_simple| `-- vbe_simple > > > > efi 0 [ + ] EFI block driver `-- > > > > /VenHw(dbca4c98-6cb0-694d-0872-819c650cb7b8) > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > > > partition 0 [ + ] blk_partition `-- efiblk#0:1 > > > > => ls efiloader 0:1 > > > >13 hello.txt > > > > 7 u-boot.txt > > > > > > > > 2 file(s), 0 dir(s) > > > > ===>8=== > > > > > > > > Signed-off-by: AKASHI Takahiro > > > > --- > > > > include/efi_driver.h | 2 +- > > > > lib/efi_driver/efi_block_device.c| 17 - > > > > lib/efi_driver/efi_uclass.c | 8 +++- > > > > lib/efi_selftest/efi_selftest_block_device.c | 2 ++ > > > > 4 files changed, 22 insertions(+), 7 deletions(-) > > > > > > > > diff --git a/include/efi_driver.h b/include/efi_driver.h > > > > index 63a95e4cf800..ed66796f3519 100644 > > > > --- a/include/efi_driver.h > > > > +++ b/include/efi_driver.h > > > > @@ -42,7 +42,7 @@ struct efi_driver_ops { > > > > const efi_guid_t *child_protocol; > > > > efi_status_t (*init)(struct > > > > efi_driver_binding_extended_protocol *this); > > > > efi_status_t (*bind)(struct > > > > efi_driver_binding_extended_protocol *this, > > > > -efi_handle_t handle, void *interface); > > > > +efi_handle_t handle, void *interface, char > > > > *name); > > > > }; > > > > > > > > #endif
Re: [RFC] efi_driver: fix a parent issue in efi-created block devices
On Wed, Jul 19, 2023 at 07:29:57PM -0600, Simon Glass wrote: > Hi, > > On Wed, 19 Jul 2023 at 18:14, AKASHI Takahiro > wrote: > > > > On Wed, Jul 19, 2023 at 03:15:10PM +0200, Heinrich Schuchardt wrote: > > > On 19.07.23 15:04, Simon Glass wrote: > > > > Hi, > > > > > > > > On Tue, 18 Jul 2023 at 19:54, AKASHI Takahiro > > > > wrote: > > > > > > > > > > Hi Simon, > > > > > > > > > > On Tue, Jul 18, 2023 at 07:08:45PM -0600, Simon Glass wrote: > > > > > > Hi AKASHI, > > > > > > > > > > > > On Tue, 18 Jul 2023 at 18:22, AKASHI Takahiro > > > > > > wrote: > > > > > > > > > > > > > > An EFI application may create an EFI block device > > > > > > > (EFI_BLOCK_IO_PROTOCOL) in > > > > > > > EFI world, which in turn generates a corresponding U-Boot block > > > > > > > device based on > > > > > > > U-Boot's Driver Model. > > > > > > > The latter device, however, doesn't work as U-Boot proper block > > > > > > > device > > > > > > > due to an issue in efi_driver's implementation. We saw > > > > > > > discussions in the past, > > > > > > > most recently in [1]. > > > > > > > > > > > > > >[1] > > > > > > > https://lists.denx.de/pipermail/u-boot/2023-July/522565.html > > > > > > > > > > > > > > This RFC patch tries to address (part of) the issue. > > > > > > > If it is considered acceptable, I will create a formal patch. > > > > > > > > > > > > > > Withtout this patch, > > > > > > > ===8<=== > > > > > > > => env set efi_selftest 'block device' > > > > > > > => bootefi selftest > > > > > > > ... > > > > > > > > > > > > > > Summary: 0 failures > > > > > > > > > > > > > > => dm tree > > > > > > > Class Index Probed DriverName > > > > > > > --- > > > > > > > root 0 [ + ] root_driver root_driver > > > > > > > ... > > > > > > > bootmeth 7 [ ] vbe_simple| `-- > > > > > > > vbe_simple > > > > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > > > > > > partition 0 [ + ] blk_partition `-- > > > > > > > efiblk#0:1 > > > > > > > => ls efiloader 0:1 > > > > > > > ** Bad device specification efiloader 0 ** > > > > > > > Couldn't find partition efiloader 0:1 > > > > > > > ===>8=== > > > > > > > > > > > > > > With this patch applied, efiblk#0(:1) now gets accessible. > > > > > > > > > > > > > > ===8<=== > > > > > > > => env set efi_selftest 'block device' > > > > > > > => bootefi selftest > > > > > > > ... > > > > > > > > > > > > > > Summary: 0 failures > > > > > > > > > > > > > > => dm tree > > > > > > > Class Index Probed DriverName > > > > > > > --- > > > > > > > root 0 [ + ] root_driver root_driver > > > > > > > ... > > > > > > > bootmeth 7 [ ] vbe_simple| `-- > > > > > > > vbe_simple > > > > > > > efi 0 [ + ] EFI block driver `-- > > > > > > > /VenHw(dbca4c98-6cb0-694d-0872-819c650cb7b8) > > > > > > > blk 0 [ + ] efi_blk `-- efiblk#0 > > > > > > > partition 0 [ + ] blk_partition `-- > > > > > > > efiblk#0:1 > > > > > > > => ls efiloader 0:1 > > > > > > > 13 hello.txt > > > > > > > 7
Re: [PATCH] efi_loader: Allow also empty capsule to be process
Hi, On Wed, Jul 19, 2023 at 08:28:41AM +0200, Michal Simek wrote: > > > On 7/18/23 17:41, Heinrich Schuchardt wrote: > > On 13.07.23 16:35, Michal Simek wrote: > > > Empty capsule are also allowed to be process. Without it updated images > > > can't change their Image Acceptance state from no to yes. > > > > Is there any documentation describing the usage of empty capsule to set > > the image acceptance state? > > I actually don't know about documentation. I was talking to Ilias to make > sure that documentation is up2date because there are missing couple of > things there. Sughosh should have more to say here about A/B update. > I am testing A/B update and if you setup oemflags to 0x8000 then capsules > are not automatically accepted and waiting for acceptance capsule to be > passed. > When I tested it I found out that they are not process that's why I created > this patch. The path you tried to modify is only executed by "efidebug capsule update" or more specifically via the runtime service, UPDATE_CAPSULE. But this API is NOT officially supported in the current capsule implementation (at least, in my initial intention). The only way to invoke capsule updates is to reboot the system. If you want to test A/B update, please do the reboot. -Takahiro Akashi > But definitely someone should check that logic that the patch is > right based on intention how these empty capsules should be used. > I am actually not quite sure how revert capsules should be used and how to > revert only certain image if you use multiple images in the same bank. > > Thanks, > Michal
Re: [PATCH] efi_loader: Allow also empty capsule to be process
On Thu, Jul 20, 2023 at 10:42:10PM +0200, Heinrich Schuchardt wrote: > On 7/20/23 11:48, Sughosh Ganu wrote: > > On Thu, 20 Jul 2023 at 14:56, Michal Simek wrote: > > > > > > > > > > > > On 7/20/23 10:45, Sughosh Ganu wrote: > > > > On Thu, 20 Jul 2023 at 13:26, Michal Simek wrote: > > > > > > > > > > > > > > > > > > > > On 7/20/23 08:36, Sughosh Ganu wrote: > > > > > > On Thu, 20 Jul 2023 at 11:37, Michal Simek > > > > > > wrote: > > > > > > > > > > > > > > Hi, > > > > > > > > > > > > > > On 7/20/23 07:49, AKASHI Takahiro wrote: > > > > > > > > Hi, > > > > > > > > > > > > > > > > On Wed, Jul 19, 2023 at 08:28:41AM +0200, Michal Simek wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > On 7/18/23 17:41, Heinrich Schuchardt wrote: > > > > > > > > > > On 13.07.23 16:35, Michal Simek wrote: > > > > > > > > > > > Empty capsule are also allowed to be process. Without it > > > > > > > > > > > updated images > > > > > > > > > > > can't change their Image Acceptance state from no to yes. > > > > > > > > > > > > > > > > > > > > Is there any documentation describing the usage of empty > > > > > > > > > > capsule to set > > > > > > > > > > the image acceptance state? > > > > > > > > > > > > > > > > > > I actually don't know about documentation. I was talking to > > > > > > > > > Ilias to make > > > > > > > > > sure that documentation is up2date because there are missing > > > > > > > > > couple of > > > > > > > > > things there. > > > > > > > > > > > > > > > > Sughosh should have more to say here about A/B update. > > > > > > > > > > > > > > > > > I am testing A/B update and if you setup oemflags to 0x8000 > > > > > > > > > then capsules > > > > > > > > > are not automatically accepted and waiting for acceptance > > > > > > > > > capsule to be > > > > > > > > > passed. > > > > > > > > > When I tested it I found out that they are not process that's > > > > > > > > > why I created > > > > > > > > > this patch. > > > > > > > > > > > > > > > > The path you tried to modify is only executed by "efidebug > > > > > > > > capsule update" > > > > > > > > or more specifically via the runtime service, UPDATE_CAPSULE. > > > > > > > > > > > > > > > > But this API is NOT officially supported in the current capsule > > > > > > > > implementation > > > > > > > > (at least, in my initial intention). > > > > > > > > The only way to invoke capsule updates is to reboot the system. > > > > > > > > If you want to test A/B update, please do the reboot. > > > > > > > > > > > > > > I realized that to get full flow you need to use capsule update > > > > > > > on disk to get > > > > > > > all functionalities. But it is very impractical. Actually I would > > > > > > > expect via > > > > > > > efidebug you should be able to perform all steps as capsule > > > > > > > update performs when > > > > > > > you do reboot. > > > > > > > I would also understand that via efidebug you are not able to > > > > > > > apply any capsule > > > > > > > but I don't think it is right that you can apply just update > > > > > > > capsules but not > > > > > > > empty capsules. I would understand none or all but not something > > > > > > > in the middle. > > > > > > > > > > > > The A/B update functionality requires using the capsule-on-disk > > > > > &
Re: [PATCH v6 08/14] firmware: scmi: add a version check against base protocol
Hi Etienne, Thank you again for your review. On Wed, Oct 11, 2023 at 03:44:36PM +, Etienne CARRIERE - foss wrote: > > 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, &version); > > + 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. Yeah, I also confirmed this. > Reviewed-by: Etienne Carriere > > That said, maybe a more flexible implementation would support both version > v1.0 (0x1) and v2.0 SCMI v2.0 (not the base protocol, but the specification itself) introduced base protocol v2.0 and the spec was published in 2019. Along with the status of the existing SCMI server implementation (as you mentioned above), I doubt any chance that there comes up any new SCMI with the base protocol v1.0 in the future. > but disable permission commands for v1.0 compliant servers. Maybe in a later > change, if there is a need for. Yes, we can make a tweak later. But anyhow "permission" commands are categorized as optional even in v2.0 (i.e. the firmware may still return SCMI_NOT_SUPPORTED) and U-Boot has no framework to utilize them for now. BTW, I will not add a version check against all the existing protocols (you implemented) as they utilize only the interfaces defined in each one's v1.0. Thanks, -Takahiro Akashi > 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 4/4] test: dm: add SCMI power domain protocol test
Hi Tom, On Fri, Oct 13, 2023 at 09:20:48PM -0400, Tom Rini wrote: > On Tue, Sep 26, 2023 at 04:00:43PM +0900, AKASHI Takahiro wrote: > > > This ut has tests for the SCMI power domain protocol as well as DM > > interfaces for power domain devices. > > > > Signed-off-by: AKASHI Takahiro > > Reviewed-by: Simon Glass > > --- > > test/dm/scmi.c | 107 - > > 1 file changed, 106 insertions(+), 1 deletion(-) > > With v6 of the required series there is no scmi command, so, how do we > test this support now? Well, "ut dm scmi_power_domains" does test the code at function level (both for SCMI protocol APIs and DM's power_domain_*() interfaces). That said, prior to v6, we needed to adjust the output from "smci info" command and hence "ut dm scmi_cmd" test because it, more specifically base protocol's DISCOVER_LIST_PROTOCOLS, tries to enumerate available protocols including power domain protocol. With v6, we can simply remove the first hunk in this commit. I will submit a new version with this change. Thanks, -Takahiro Akashi > > -- > Tom signature.asc Description: PGP signature
[PATCH v2 0/4] firmware: scmi: add SCMI power domain protocol support
This patch series allows users to access SCMI power domain protocol provided by SCMI server (platform). See SCMI specification document v3.2 beta 2[1] for more details about SCMI power domain protocol. The implementation consists of two layers: - basic helper functions for SCMI power domain protocol in drivers/firmware/scmi/pwdom.c (patch#1) - DM-compliant power domain driver, which utilizes the helper functions, in drivers/power/domain/scmi-power-domain.c (patch#2) [1] https://developer.arm.com/documentation/den0056/e/?lang=en DT bindings === Standard bindings are applied, i.e. scmi { ... pwrdom_scmi: protocol@11 { regs = <0x11>; #power-domain-cells = <1>; } ... } som-device { ... power-domains = <&pwrdom_scmi 2>; } Test The patch series was tested on the following platform: * sandbox ("ut dm scmi_power_domains") Prerequisite: = * This patch series is based on the master which now includes my "Base protocol support" patches v6[2] [2] https://lists.denx.de/pipermail/u-boot/2023-September/531623.html Patches: Patch#1: Add SCMI power domain protocol helpers Patch#2: Add power domain driver Patch#3-#4: Test related Change history: === v2 (Oct 16, 2023) * remove a change on "test_scmi_cmd" because "scmi" command is no longer provided with base protocol v6 * some cleanup v1 (Sep 26, 2023) * initial release AKASHI Takahiro (4): firmware: scmi: add power domain protocol support power: domain: add SCMI driver sandbox: add SCMI power domain protocol support for testing test: dm: add SCMI power domain protocol test arch/sandbox/dts/test.dts| 6 + arch/sandbox/include/asm/scmi_test.h | 21 ++ configs/sandbox_defconfig| 1 + drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/pwdom.c| 189 + drivers/firmware/scmi/sandbox-scmi_agent.c | 265 ++- drivers/firmware/scmi/sandbox-scmi_devices.c | 10 + drivers/firmware/scmi/scmi_agent-uclass.c| 11 + drivers/power/domain/Kconfig | 7 + drivers/power/domain/Makefile| 1 + drivers/power/domain/scmi-power-domain.c | 193 ++ include/scmi_agent-uclass.h | 2 + include/scmi_protocols.h | 178 + test/dm/scmi.c | 103 +++ 14 files changed, 987 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/scmi/pwdom.c create mode 100644 drivers/power/domain/scmi-power-domain.c -- 2.34.1
[PATCH v2 2/4] power: domain: add SCMI driver
Add power domain driver based on SCMI power domain management protocol. Signed-off-by: AKASHI Takahiro --- v2 * remove tentative code which was enclosed by "#if 0" * free allocated memory at the failure of probe function --- drivers/firmware/scmi/scmi_agent-uclass.c | 11 ++ drivers/power/domain/Kconfig | 7 + drivers/power/domain/Makefile | 1 + drivers/power/domain/scmi-power-domain.c | 193 ++ include/scmi_agent-uclass.h | 2 + 5 files changed, 214 insertions(+) create mode 100644 drivers/power/domain/scmi-power-domain.c diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 6f585b96f740..0f1003e167e6 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -86,6 +86,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_BASE: proto = priv->base_dev; break; + case SCMI_PROTOCOL_ID_POWER_DOMAIN: + proto = priv->pwdom_dev; + break; case SCMI_PROTOCOL_ID_CLOCK: proto = priv->clock_dev; break; @@ -133,6 +136,9 @@ static int scmi_add_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_BASE: priv->base_dev = proto; break; + case SCMI_PROTOCOL_ID_POWER_DOMAIN: + priv->pwdom_dev = proto; + break; case SCMI_PROTOCOL_ID_CLOCK: priv->clock_dev = proto; break; @@ -405,6 +411,11 @@ static int scmi_bind_protocols(struct udevice *dev) drv = NULL; name = ofnode_get_name(node); switch (protocol_id) { + case SCMI_PROTOCOL_ID_POWER_DOMAIN: + if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN) && + scmi_protocol_is_supported(dev, protocol_id)) + drv = DM_DRIVER_GET(scmi_power_domain); + break; case SCMI_PROTOCOL_ID_CLOCK: if (CONFIG_IS_ENABLED(CLK_SCMI) && scmi_protocol_is_supported(dev, protocol_id)) diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 411c210756a3..bd82d2f7044b 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -83,6 +83,13 @@ config SANDBOX_POWER_DOMAIN simply accepts requests to power on/off various HW modules without actually doing anything beyond a little error checking. +config SCMI_POWER_DOMAIN + bool "Enable SCMI power domain driver" + depends on POWER_DOMAIN && SCMI_FIRMWARE + help + Enable power domain implementation based on SCMI power domain + management protocol. + config TEGRA186_POWER_DOMAIN bool "Enable Tegra186 BPMP-based power domain driver" depends on TEGRA186_BPMP diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index aa5a4ba57cd8..2daab73eb758 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o obj-$(CONFIG_MESON_SECURE_POWER_DOMAIN) += meson-secure-pwrc.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o +obj-$(CONFIG_SCMI_POWER_DOMAIN) += scmi-power-domain.o obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o obj-$(CONFIG_TI_SCI_POWER_DOMAIN) += ti-sci-power-domain.o obj-$(CONFIG_TI_POWER_DOMAIN) += ti-power-domain.o diff --git a/drivers/power/domain/scmi-power-domain.c b/drivers/power/domain/scmi-power-domain.c new file mode 100644 index ..2b85efc08914 --- /dev/null +++ b/drivers/power/domain/scmi-power-domain.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SCMI Power domain driver + * + * Copyright (C) 2023 Linaro Limited + * author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct scmi_pwd_properties + * @attributes:Power domain attributes + * @name: Name of the domain + */ +struct scmi_pwd_properties { + u32 attributes; + u8 *name; /* not used now */ +}; + +/** + * struct scmi_power_domain_priv + * @num_pwdoms:Number of power domains + * @prop: Pointer to domain's properties + * @stats_addr:Address of statistics memory region + * @stats_len: Length of statistics memory region + */ +struct scmi_power_domain_priv { + int num_pwdoms; + struct scmi_pwd_properties *prop; + u64 stats_addr; + size_t stats_len; +}; + +/** + * async_is_supported - check asynchronous transition + * @attributes:Power domain attributes + * + * Determin
[PATCH v2 3/4] sandbox: add SCMI power domain protocol support for testing
SCMI power domain management protocol is supported on sandbox for test purpose. Add fake agent interfaces and associated power domain devices. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass --- v2 * add a comment for a member, pstate, of struct sandbox_scmi_pwd --- arch/sandbox/dts/test.dts| 6 + arch/sandbox/include/asm/scmi_test.h | 21 ++ configs/sandbox_defconfig| 1 + drivers/firmware/scmi/sandbox-scmi_agent.c | 265 ++- drivers/firmware/scmi/sandbox-scmi_devices.c | 10 + 5 files changed, 302 insertions(+), 1 deletion(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index c0ed2d83f3d2..309127a91004 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -732,6 +732,11 @@ #address-cells = <1>; #size-cells = <0>; + pwrdom_scmi: protocol@11 { + reg = <0x11>; + #power-domain-cells = <1>; + }; + clk_scmi: protocol@14 { reg = <0x14>; #clock-cells = <1>; @@ -1635,6 +1640,7 @@ sandbox_scmi { compatible = "sandbox,scmi-devices"; + power-domains = <&pwrdom_scmi 2>; clocks = <&clk_scmi 2>, <&clk_scmi 0>; resets = <&reset_scmi 3>; regul0-supply = <®ul0_scmi>; diff --git a/arch/sandbox/include/asm/scmi_test.h b/arch/sandbox/include/asm/scmi_test.h index ccb0df6c148f..619f8f5098cd 100644 --- a/arch/sandbox/include/asm/scmi_test.h +++ b/arch/sandbox/include/asm/scmi_test.h @@ -6,10 +6,22 @@ #ifndef __SANDBOX_SCMI_TEST_H #define __SANDBOX_SCMI_TEST_H +#include + struct udevice; struct sandbox_scmi_agent; struct sandbox_scmi_service; +/** + * struct sandbox_scmi_pwd + * @id:Identifier of the power domain used in the SCMI protocol + * @pstate:: Power state of the domain + */ +struct sandbox_scmi_pwd { + uint id; + u32 pstate; +}; + /** * struct sandbox_scmi_clk - Simulated clock exposed by SCMI * @id:Identifier of the clock used in the SCMI protocol @@ -45,6 +57,8 @@ struct sandbox_scmi_voltd { /** * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent + * @pwdom_version: Implemented power domain protocol version + * @pwdom_count: Simulated power domains array size * @clk: Simulated clocks * @clk_count: Simulated clocks array size * @reset: Simulated reset domains @@ -53,6 +67,9 @@ struct sandbox_scmi_voltd { * @voltd_count: Simulated voltage domains array size */ struct sandbox_scmi_agent { + int pwdom_version; + struct sandbox_scmi_pwd *pwdom; + size_t pwdom_count; struct sandbox_scmi_clk *clk; size_t clk_count; struct sandbox_scmi_reset *reset; @@ -71,6 +88,8 @@ struct sandbox_scmi_service { /** * struct sandbox_scmi_devices - Reference to devices probed through SCMI + * @pwdom: Array of power domains + * @pwdom_count: Number of power domains probed * @clk: Array the clock devices * @clk_count: Number of clock devices probed * @reset: Array the reset controller devices @@ -79,6 +98,8 @@ struct sandbox_scmi_service { * @regul_count: Number of regulator devices probed */ struct sandbox_scmi_devices { + struct power_domain *pwdom; + size_t pwdom_count; struct clk *clk; size_t clk_count; struct reset_ctl *reset; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 01830c7bd255..dbee9eb7f571 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -241,6 +241,7 @@ CONFIG_PINCTRL_SANDBOX=y CONFIG_PINCTRL_SINGLE=y CONFIG_POWER_DOMAIN=y CONFIG_SANDBOX_POWER_DOMAIN=y +CONFIG_SCMI_POWER_DOMAIN=y CONFIG_DM_PMIC=y CONFIG_PMIC_ACT8846=y CONFIG_DM_PMIC_PFUZE100=y diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index eb567dd900d7..9f5f497e0a6c 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -43,6 +43,8 @@ #define SANDBOX_SCMI_AGENT_NAME "OSPM" #define SANDBOX_SCMI_PLATFORM_NAME "platform" +#define SANDBOX_SCMI_PWD_PROTOCOL_VERSION SCMI_PWD_PROTOCOL_VERSION + /** * struct sandbox_channel - Description of sandbox transport * @channel_id:Channel identifier @@ -64,6 +66,7 @@ struct scmi_channel { }; static u8 protocols[] = { + SCMI_PROTOCOL_ID_POWER_DOMAIN, SCMI_PROTOCOL_ID_CLOCK, SCMI_PROTOCOL_ID_RESET_DOMAIN, SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, @@ -71,6 +74,12 @@ static u8 protocols[] = { #define NUM_PROTO
[PATCH v2 4/4] test: dm: add SCMI power domain protocol test
This ut has tests for the SCMI power domain protocol as well as DM interfaces for power domain devices. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass --- v2 * remove a change at "test_scmi_cmd" because "scmi" command is no longer provided --- test/dm/scmi.c | 103 + 1 file changed, 103 insertions(+) diff --git a/test/dm/scmi.c b/test/dm/scmi.c index d4ff60e00069..da45314f2e4c 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -206,6 +206,109 @@ 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_power_domains(struct unit_test_state *uts) +{ + struct sandbox_scmi_agent *agent; + struct sandbox_scmi_devices *scmi_devices; + struct udevice *agent_dev, *pwd, *dev; + u32 version, count, attributes, pstate; + u64 stats_addr; + size_t stats_len; + u8 *name; + int ret; + + /* preparation */ + ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev)); + ut_assertnonnull(agent); + scmi_devices = sandbox_scmi_devices_ctx(dev); + ut_assertnonnull(scmi_devices); + ut_asserteq(2, scmi_devices->pwdom->id); /* in test.dts */ + + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", + &agent_dev)); + ut_assertnonnull(agent_dev); + pwd = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_POWER_DOMAIN); + ut_assertnonnull(pwd); + + /* +* SCMI Power domain management protocol interfaces +*/ + /* version */ + ret = scmi_generic_protocol_version(pwd, SCMI_PROTOCOL_ID_POWER_DOMAIN, + &version); + ut_assertok(ret); + ut_asserteq(agent->pwdom_version, version); + + /* protocol attributes */ + ret = scmi_pwd_protocol_attrs(pwd, &count, &stats_addr, &stats_len); + ut_assertok(ret); + ut_asserteq(agent->pwdom_count, count); + ut_asserteq(0, stats_len); + + /* protocol message attributes */ + ret = scmi_pwd_protocol_message_attrs(pwd, SCMI_PWD_STATE_SET, + &attributes); + ut_assertok(ret); + ret = scmi_pwd_protocol_message_attrs(pwd, SCMI_PWD_STATE_NOTIFY, + &attributes); + ut_asserteq(-ENOENT, ret); /* the protocol not supported */ + + /* power domain attributes */ + ret = scmi_pwd_attrs(pwd, 0, &attributes, &name); + ut_assertok(ret); + ut_asserteq_str("power-domain--0", name); + free(name); + + ret = scmi_pwd_attrs(pwd, 10, &attributes, &name); + ut_asserteq(-ENOENT, ret); /* domain-10 doesn't exist */ + + /* power domain state set/get */ + ret = scmi_pwd_state_set(pwd, 0, 0, 0); + ut_assertok(ret); + ret = scmi_pwd_state_get(pwd, 0, &pstate); + ut_assertok(ret); + ut_asserteq(0, pstate); /* ON */ + + ret = scmi_pwd_state_set(pwd, 0, 0, SCMI_PWD_PSTATE_TYPE_LOST); + ut_assertok(ret); + ret = scmi_pwd_state_get(pwd, 0, &pstate); + ut_assertok(ret); + ut_asserteq(SCMI_PWD_PSTATE_TYPE_LOST, pstate); /* OFF */ + + ret = scmi_pwd_state_set(pwd, 0, 10, 0); + ut_asserteq(-ENOENT, ret); + + /* power domain name get */ + ret = scmi_pwd_name_get(pwd, 0, &name); + ut_assertok(ret); + ut_asserteq_str("power-domain--0-extended", name); + free(name); + + ret = scmi_pwd_name_get(pwd, 10, &name); + ut_asserteq(-ENOENT, ret); /* domain-10 doesn't exist */ + + /* +* U-Boot driver model interfaces +*/ + /* power_domain_on */ + ret = power_domain_on(scmi_devices->pwdom); + ut_assertok(ret); + ret = scmi_pwd_state_get(pwd, scmi_devices->pwdom->id, &pstate); + ut_assertok(ret); + ut_asserteq(0, pstate); /* ON */ + + /* power_domain_off */ + ret = power_domain_off(scmi_devices->pwdom); + ut_assertok(ret); + ret = scmi_pwd_state_get(pwd, scmi_devices->pwdom->id, &pstate); + ut_assertok(ret); + ut_asserteq(SCMI_PWD_PSTATE_TYPE_LOST, pstate); /* OFF */ + + return release_sandbox_scmi_test_devices(uts, dev); +} + +DM_TEST(dm_test_scmi_power_domains, UT_TESTF_SCAN_FDT); + static int dm_test_scmi_clocks(struct unit_test_state *uts) { struct sandbox_scmi_agent *agent; -- 2.34.1
[PATCH v2 1/4] firmware: scmi: add power domain protocol support
In this patch, added are helper functions to directly manipulate SCMI power domain management protocol. DM compliant power domain driver will be implemented on top of those interfaces in a succeeding patch. Signed-off-by: AKASHI Takahiro --- drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/pwdom.c | 189 + include/scmi_protocols.h | 178 +++ 3 files changed, 368 insertions(+) create mode 100644 drivers/firmware/scmi/pwdom.c diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index 1a23d4981709..dae42863589a 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -4,4 +4,5 @@ obj-y += smt.o obj-$(CONFIG_SCMI_AGENT_SMCCC) += smccc_agent.o obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SCMI_AGENT_OPTEE) += optee_agent.o +obj-$(CONFIG_SCMI_POWER_DOMAIN)+= pwdom.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o diff --git a/drivers/firmware/scmi/pwdom.c b/drivers/firmware/scmi/pwdom.c new file mode 100644 index ..61b4338663de --- /dev/null +++ b/drivers/firmware/scmi/pwdom.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SCMI Power domain management protocol + * + * Copyright (C) 2023 Linaro Limited + * author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include +#include + +int scmi_pwd_protocol_attrs(struct udevice *dev, int *num_pwdoms, + u64 *stats_addr, size_t *stats_len) +{ + struct scmi_pwd_protocol_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN, + .message_id = SCMI_PROTOCOL_ATTRIBUTES, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !num_pwdoms || !stats_addr || !stats_len) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *num_pwdoms = SCMI_PWD_PROTO_ATTRS_NUM_PWD(out.attributes); + *stats_addr = ((u64)out.stats_addr_high << 32) + out.stats_addr_low; + *stats_len = out.stats_len; + + return 0; +} + +int scmi_pwd_protocol_message_attrs(struct udevice *dev, s32 message_id, + u32 *attributes) +{ + struct scmi_pwd_protocol_msg_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN, + .message_id = SCMI_PROTOCOL_MESSAGE_ATTRIBUTES, + .in_msg = (u8 *)&message_id, + .in_msg_sz = sizeof(message_id), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !attributes) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *attributes = out.attributes; + + return 0; +} + +int scmi_pwd_attrs(struct udevice *dev, u32 domain_id, u32 *attributes, + u8 **name) +{ + struct scmi_pwd_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN, + .message_id = SCMI_PWD_ATTRIBUTES, + .in_msg = (u8 *)&domain_id, + .in_msg_sz = sizeof(domain_id), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !attributes || !name) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *name = strdup(out.name); + if (!*name) + return -ENOMEM; + + *attributes = out.attributes; + + return 0; +} + +int scmi_pwd_state_set(struct udevice *dev, u32 flags, u32 domain_id, + u32 pstate) +{ + struct scmi_pwd_state_set_in in; + s32 status; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_POWER_DOMAIN, + .message_id = SCMI_PWD_STATE_SET, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.flags = flags; + in.domain_id = domain_id; + in.pstate = pstate; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (status) + retu
Re: [PATCH v3 21/32] efi: Rearrange the Kconfig for CMD_BOOTEFI_BOOTMGR
Hi Simon, Thank you for taking my idea here. On Mon, Oct 16, 2023 at 04:28:12PM -0600, Simon Glass wrote: > The command should not be used to enable library functionality. Add a > new BOOTEFI_BOOTMGR Kconfig for that. Adjust the conditions so that the > same code is built. > > Signed-off-by: Simon Glass > Suggested-by: AKASHI Takahiro > --- > > Changes in v3: > - Add new patch to rearrange the Kconfig for CMD_BOOTEFI_BOOTMGR > > cmd/Kconfig | 9 + > lib/efi_loader/Kconfig | 7 +++ > lib/efi_loader/Makefile | 2 +- > 3 files changed, 13 insertions(+), 5 deletions(-) > > diff --git a/cmd/Kconfig b/cmd/Kconfig > index 46e484fc08b6..3b4112d9f319 100644 > --- a/cmd/Kconfig > +++ b/cmd/Kconfig > @@ -306,6 +306,15 @@ config CMD_BOOTI > help > Boot an AArch64 Linux Kernel image from memory. > > +config CMD_BOOTEFI_BOOTMGR > + bool "UEFI Boot Manager command" > + depends on BOOTEFI_BOOTMGR && CMD_BOOTEFI > + default y > + help > + Select this option if you want to select the UEFI binary to be booted > + via UEFI variables Boot, BootOrder, and BootNext. This enables the > + 'bootefi bootmgr' command. > + > config BOOTM_LINUX Do you have any intention to put this configuration here? Otherwise, it should be placed just after CMD_BOOTEFI. In addition, CMD_EFICONFIG should have a dependency on BOOTEFI_BOOTMGR rather than CMD_BOOTEFI_BOOTMGR as it is a separate command. Thanks, -Takahiro Akashi > bool "Support booting Linux OS images" > depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > index 621ed5e5b0fb..13cad6342c36 100644 > --- a/lib/efi_loader/Kconfig > +++ b/lib/efi_loader/Kconfig > @@ -32,15 +32,14 @@ config EFI_LOADER > > if EFI_LOADER > > -config CMD_BOOTEFI_BOOTMGR > +config BOOTEFI_BOOTMGR > bool "UEFI Boot Manager" > - depends on CMDLINE > default y > select BOOTMETH_GLOBAL if BOOTSTD > help > Select this option if you want to select the UEFI binary to be booted > - via UEFI variables Boot, BootOrder, and BootNext. This enables the > - 'bootefi bootmgr' command. > + via UEFI variables Boot, BootOrder, and BootNext. You should also > + normally enable CMD_BOOTEFI_BOOTMGR so that the command is available. > > choice > prompt "Store for non-volatile UEFI variables" > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile > index 8d31fc61c601..0a2cb6e3c476 100644 > --- a/lib/efi_loader/Makefile > +++ b/lib/efi_loader/Makefile > @@ -42,7 +42,7 @@ targets += initrddump.o > endif > > obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o > -obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o > +obj-$(CONFIG_BOOTEFI_BOOTMGR) += efi_bootmgr.o > obj-y += efi_boottime.o > obj-y += efi_helper.o > obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o > -- > 2.42.0.655.g421f12c284-goog >
Re: [PATCH v3 22/32] efi: Update EFI_LOADER to depend on DM_ETH
On Thu, Oct 19, 2023 at 08:01:11AM -0600, Simon Glass wrote: > Hi Heinrich, > > On Wed, 18 Oct 2023 at 06:55, Heinrich Schuchardt wrote: > > > > On 10/17/23 16:09, Tom Rini wrote: > > > On Mon, Oct 16, 2023 at 04:28:13PM -0600, Simon Glass wrote: > > > > > >> Since efi_device_path.c calls eth_get_dev() and assumes that Ethernet is > > >> available, add it as an explicit dependency. > > >> > > >> Signed-off-by: Simon Glass > > >> --- > > >> > > >> (no changes since v2) > > >> > > >> Changes in v2: > > >> - Add new patch to update EFI_LOADER to depend on DM_ETH > > >> > > >> lib/efi_loader/Kconfig | 1 + > > >> 1 file changed, 1 insertion(+) > > >> > > >> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > > >> index 13cad6342c36..fca4b3eef270 100644 > > >> --- a/lib/efi_loader/Kconfig > > >> +++ b/lib/efi_loader/Kconfig > > >> @@ -11,6 +11,7 @@ config EFI_LOADER > > >> # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB > > >> depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT > > >> depends on BLK > > >> +depends on DM_ETH > > >> depends on !EFI_APP > > >> default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8 > > >> select CHARSET > > > > > > Does this work for you Heinrich, or do you want to clarify the > > > dependencies (and re-organize the code as needed) around networking? > > > > > > > We should be able to boot via EFI on devices without U-Boot network support. > > > > We already use IS_ENABLED(CONFIG_NETDEVICES) to avoid invoking > > eth_get_dev() if there is no network. CONFIG_NETDEVICES=y selects > > CONFIG_DM_ETH. > > > > Why is this not sufficient? > > Is there a configuration that does not build? > > The point of this series is to disable CMDLINE and fix up what breaks. > > In this case we have some sort of breakage...perhaps Tom has already > found it, but otherwise could you take a look? > > We should be able to disable NET and LTO in sandbox and still build. > But this fails at present[1]. You can try it on -master Obviously, it would be necessary to enclose efi_dp_from_eth() with "if defined(CONFIG_NETDEVICES)" (or DM_ETH). Then, we could drop "depends on DM_ETH". Another possible place for completeness is "case UCLASS_ETH" clause in dp_size(), but it seems to be harmless. -Takahiro Akashi > Regards, > Simon > > [1] sjg@sjg1:~/u$ crosfw sandbox -L > cmd: make -j4 'CROSS_COMPILE=' --no-print-directory 'HOSTSTRIP=true' > 'QEMU_ARCH=' 'KCONFIG_NOSILENTUPDATE=1' 'O=/tmp/b/sandbox' 'NO_LTO=1' > -s 'BUILD_ROM=1' all > /usr/bin/ld: lib/efi_loader/efi_device_path.o: in function `efi_dp_from_eth': > /home/sjg/c/src/third_party/u-boot/files/lib/efi_loader/efi_device_path.c:985:(.text+0xca4): > undefined reference to `eth_get_dev' > /usr/bin/ld: > /home/sjg/c/src/third_party/u-boot/files/lib/efi_loader/efi_device_path.c:987:(.text+0xca9): > undefined reference to `eth_get_dev' > /usr/bin/ld: > /home/sjg/c/src/third_party/u-boot/files/lib/efi_loader/efi_device_path.c:993:(.text+0xcc9): > undefined reference to `eth_get_dev' > collect2: error: ld returned 1 exit status > make[1]: *** [/home/sjg/c/src/third_party/u-boot/files/Makefile:1765: > u-boot] Error 1 > make: *** [Makefile:177: sub-make] Error 2 > > sjg@sjg1:~/u$ crosfw sandbox > sjg@sjg1:~/u$ (passes) > > 'crosfw xx' is just 'buildman --bo xxx' > > diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c > index a92bb896c63e..4e9996a92342 100644 > --- a/boot/pxe_utils.c > +++ b/boot/pxe_utils.c > @@ -48,7 +48,7 @@ int pxe_get_file_size(ulong *sizep) > > return 0; > } > - > +#if 0 > /** > * format_mac_pxe() - obtain a MAC address in the PXE format > * > @@ -82,7 +82,7 @@ int format_mac_pxe(char *outbuf, size_t outbuf_len) > > return 1; > } > - > +#endif > /** > * get_relfile() - read a file relative to the PXE file > * > diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig > index 47417cb0391d..57bb6202dbb5 100644 > --- a/configs/sandbox_defconfig > +++ b/configs/sandbox_defconfig > @@ -349,3 +349,4 @@ CONFIG_TEST_FDTDEC=y > CONFIG_UNIT_TEST=y > CONFIG_UT_TIME=y > CONFIG_UT_DM=y > +# CONFIG_NET is not set > > Regards, > Simon
Re: [v4 11/24] efi: Rearrange the Kconfig for CMD_BOOTEFI_BOOTMGR
On Thu, Oct 19, 2023 at 11:19:33AM -0400, Tom Rini wrote: > On Thu, Oct 19, 2023 at 05:16:28PM +0200, Heinrich Schuchardt wrote: > > On 19.10.23 17:00, Tom Rini wrote: > > > From: Simon Glass > > > > > > The command should not be used to enable library functionality. Add a > > > new BOOTEFI_BOOTMGR Kconfig for that. Adjust the conditions so that the > > > same code is built. > > > > > > Signed-off-by: Simon Glass > > > Suggested-by: AKASHI Takahiro > > > --- > > > Cc: Heinrich Schuchardt > > > Cc: Ilias Apalodimas > > > Changes in v4: > > > - Integrate AKASHI Takahiro's feedback from v3 > > > - Reword the help text on CMD_BOOTEFI_BOOTMGR slightly > > > --- > > > cmd/Kconfig | 11 ++- > > > lib/efi_loader/Kconfig | 6 +++--- > > > lib/efi_loader/Makefile | 2 +- > > > 3 files changed, 14 insertions(+), 5 deletions(-) > > > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > > index 16e5cb8f0633..872cb49150cc 100644 > > > --- a/cmd/Kconfig > > > +++ b/cmd/Kconfig > > > @@ -379,6 +379,15 @@ config CMD_BOOTEFI > > > help > > > Boot an EFI image from memory. > > > +config CMD_BOOTEFI_BOOTMGR > > > + bool "UEFI Boot Manager command" > > > + depends on BOOTEFI_BOOTMGR && CMD_BOOTEFI > > > + default y > > > + help > > > + Select this option to enable the 'bootmgr' subcommand of 'bootefi'. > > > + This subcommand will allow you to select the UEFI binary to be booted > > > + via UEFI variables Boot, BootOrder, and BootNext. > > > + > > > config CMD_BOOTEFI_HELLO_COMPILE > > > bool "Compile a standard EFI hello world binary for testing" > > > depends on CMD_BOOTEFI && !CPU_V7M > > > @@ -2110,7 +2119,7 @@ config CMD_EFIDEBUG > > > config CMD_EFICONFIG > > > bool "eficonfig - provide menu-driven uefi variables > > > maintenance interface" > > > default y if !HAS_BOARD_SIZE_LIMIT > > > - depends on CMD_BOOTEFI_BOOTMGR > > > + depends on BOOTEFI_BOOTMGR > > > select MENU > > > help > > > Enable the 'eficonfig' command which provides the menu-driven > > > UEFI > > > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig > > > index d20aaab6dba4..13cad6342c36 100644 > > > --- a/lib/efi_loader/Kconfig > > > +++ b/lib/efi_loader/Kconfig > > > @@ -32,14 +32,14 @@ config EFI_LOADER > > > if EFI_LOADER > > > -config CMD_BOOTEFI_BOOTMGR > > > +config BOOTEFI_BOOTMGR > > > bool "UEFI Boot Manager" > > > default y > > > select BOOTMETH_GLOBAL if BOOTSTD > > > help > > > Select this option if you want to select the UEFI binary to > > > be booted > > > - via UEFI variables Boot, BootOrder, and BootNext. This enables the > > > - 'bootefi bootmgr' command. > > > + via UEFI variables Boot, BootOrder, and BootNext. You should also > > > + normally enable CMD_BOOTEFI_BOOTMGR so that the command is available. > > > choice > > > prompt "Store for non-volatile UEFI variables" > > > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile > > > index 8d31fc61c601..0a2cb6e3c476 100644 > > > --- a/lib/efi_loader/Makefile > > > +++ b/lib/efi_loader/Makefile > > > @@ -42,7 +42,7 @@ targets += initrddump.o > > > endif > > > obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o > > > -obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o > > > +obj-$(CONFIG_BOOTEFI_BOOTMGR) += efi_bootmgr.o > > > obj-y += efi_boottime.o > > > obj-y += efi_helper.o > > > obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o > > > > This patch looks wrong. > > > > Symbol CONFIG_CMD_BOOTEFI_BOOTMGR is used in a lot of places where it is not > > related to the 'bootefi bootmgr' subcommand. > > > > I see no benefit in two separate symbols. If you want to rename the symbol, > > please, replace *all* occurrences: > > > > %s/CONFIG_CMD_BOOTEFI_BOOTMGR/CONFIG_BOOTEFI_BOOTMGR/ > > Yes, there's work on the EFI_LOADER side of things to support the use > case of "boot to menu" (or, "boot to efi bootmgr") of which this is the > starting point. The follow-up work that I'm hoping you or someone else > with more EFI_LOADER experience will pick up is splitting cmd/bootefi.c > such that we can call in to starting an EFI payload (or bootmgr) without > the command line. I will be able to take care unless Heinrich wants to do by himself. # Test would be another issue now that "bootefi" may handle various boot scenarios. -Takahiro Akashi > > -- > Tom signature.asc Description: PGP signature
Re: [PATCH v5 14/16] cmd: add scmi command for SCMI firmware
Hi Tom, Michal, On Tue, Oct 24, 2023 at 06:24:07PM -0400, Tom Rini wrote: > On Tue, Oct 24, 2023 at 10:27:44AM +0200, Michal Simek wrote: > > Hi Takahiro, > > > > ?t 26. 9. 2023 v 9:00 odes?latel AKASHI Takahiro > > napsal: > > > > > > 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 > > > Reviewed-by: Simon Glass > > > Reviewed-by: Etienne Carriere > > > --- > > > v3 > > > * describe that arguments are in hex at a help message > > > * modify the code for dynamically allocated agent names > > > v2 > > > * remove sub command category, 'scmi base', for simplicity > > > --- > > > cmd/Kconfig | 9 ++ > > > cmd/Makefile | 1 + > > > cmd/scmi.c | 337 +++ > > > 3 files changed, 347 insertions(+) > > > create mode 100644 cmd/scmi.c > > > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > > index 43ca10f69ccf..f46152ace7d8 100644 > > > --- a/cmd/Kconfig > > > +++ b/cmd/Kconfig > > > @@ -2533,6 +2533,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 > > > > This line above is wrong and this was removed from v6 with @Michal, do you mean the default should be 'y'? > > "drop scmi command which was intended to be used for debugging". > > It is fine that it shouldn't be used on production system but it > > doesn't mean that > > it should be actually removed. > > It is useful for bring ups. Can we get this patch merged? It was > > already reviewed > > anyway. > > There was then also some conflict with the follow-up series here. I > would be fine with the command being introduced again after I merge that > second series, which I am testing now. I don't mind neither. My concern, however, was a test, "ut dm scmi_cmd". The output from "scmi info" command varies depending on what SCMI protocols are provided by SCMI firmware (sandbox fake server in this case). I will try to keep it updated. -Takahiro Akashi > > -- > Tom signature.asc Description: PGP signature
[PATCH 0/5] cmd: add scmi command
"Scmi" command will be re-introduced per Michal's request. The functionality is the same as I put it in my patch set of adding SCMI base protocol support, but made some tweak to make UT, "ut dm scmi_cmd," more flexible and tolerable when enabling/disabling a specific SCMI protocol for test purpose. Each commit may have some change history inherited from the preceding patch series. Test The patch series was tested on the following platforms: * sandbox Prerequisite: = * This patch series is based on the latest master. AKASHI Takahiro (5): test: dm: skip scmi tests against disabled protocols firmware: scmi: support protocols on sandbox only if enabled cmd: add scmi command for SCMI firmware doc: cmd: add documentation for scmi test: dm: add scmi command test cmd/Kconfig | 9 + cmd/Makefile | 1 + cmd/scmi.c | 335 +++ configs/sandbox_defconfig| 1 + doc/usage/cmd/scmi.rst | 126 +++ doc/usage/index.rst | 1 + drivers/firmware/scmi/sandbox-scmi_agent.c | 27 +- drivers/firmware/scmi/sandbox-scmi_devices.c | 78 +++-- test/dm/scmi.c | 93 + 9 files changed, 638 insertions(+), 33 deletions(-) create mode 100644 cmd/scmi.c create mode 100644 doc/usage/cmd/scmi.rst -- 2.34.1
[PATCH 1/5] test: dm: skip scmi tests against disabled protocols
This is a precautious change to make scmi tests workable whether or not a specific protocol be enabled. Signed-off-by: AKASHI Takahiro --- test/dm/scmi.c | 12 1 file changed, 12 insertions(+) diff --git a/test/dm/scmi.c b/test/dm/scmi.c index da45314f2e4c..2f63f2da16fb 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -217,6 +217,9 @@ static int dm_test_scmi_power_domains(struct unit_test_state *uts) u8 *name; int ret; + if (!IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)) + return 0; + /* preparation */ ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev)); ut_assertnonnull(agent); @@ -317,6 +320,9 @@ static int dm_test_scmi_clocks(struct unit_test_state *uts) int ret_dev; int ret; + if (!IS_ENABLED(CONFIG_CLK_SCMI)) + return 0; + ret = load_sandbox_scmi_test_devices(uts, &agent, &dev); if (ret) return ret; @@ -382,6 +388,9 @@ static int dm_test_scmi_resets(struct unit_test_state *uts) struct udevice *agent_dev, *reset_dev, *dev = NULL; int ret; + if (!IS_ENABLED(CONFIG_RESET_SCMI)) + return 0; + ret = load_sandbox_scmi_test_devices(uts, &agent, &dev); if (ret) return ret; @@ -418,6 +427,9 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) struct udevice *dev; struct udevice *regul0_dev; + if (!IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) + return 0; + ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev)); scmi_devices = sandbox_scmi_devices_ctx(dev); -- 2.34.1
[PATCH 2/5] firmware: scmi: support protocols on sandbox only if enabled
This change will be useful when we manually test SCMI on sandbox by enabling/disabling a specific SCMI protocol. Signed-off-by: AKASHI Takahiro --- drivers/firmware/scmi/sandbox-scmi_agent.c | 27 ++- drivers/firmware/scmi/sandbox-scmi_devices.c | 78 2 files changed, 72 insertions(+), 33 deletions(-) diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 9f5f497e0a6c..e1b9b5f5f2d8 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -66,10 +66,18 @@ struct scmi_channel { }; static u8 protocols[] = { +#if IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN) SCMI_PROTOCOL_ID_POWER_DOMAIN, +#endif +#if IS_ENABLED(CONFIG_CLK_SCMI) SCMI_PROTOCOL_ID_CLOCK, +#endif +#if IS_ENABLED(CONFIG_RESET_SCMI) SCMI_PROTOCOL_ID_RESET_DOMAIN, +#endif +#if IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, +#endif }; #define NUM_PROTOCOLS ARRAY_SIZE(protocols) @@ -1160,6 +1168,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_POWER_DOMAIN: + if (!IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)) + goto not_supported; + switch (msg->message_id) { case SCMI_PROTOCOL_VERSION: return sandbox_scmi_pwd_protocol_version(dev, msg); @@ -1180,6 +1191,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_CLOCK: + if (!IS_ENABLED(CONFIG_CLK_SCMI)) + goto not_supported; + switch (msg->message_id) { case SCMI_PROTOCOL_ATTRIBUTES: return sandbox_scmi_clock_protocol_attribs(dev, msg); @@ -1196,6 +1210,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: + if (!IS_ENABLED(CONFIG_RESET_SCMI)) + goto not_supported; + switch (msg->message_id) { case SCMI_RESET_DOMAIN_ATTRIBUTES: return sandbox_scmi_rd_attribs(dev, msg); @@ -1206,6 +1223,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: + if (!IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) + goto not_supported; + switch (msg->message_id) { case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES: return sandbox_scmi_voltd_attribs(dev, msg); @@ -1224,8 +1244,7 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, case SCMI_PROTOCOL_ID_SYSTEM: case SCMI_PROTOCOL_ID_PERF: case SCMI_PROTOCOL_ID_SENSOR: - *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; - return 0; + goto not_supported; default: break; } @@ -1239,6 +1258,10 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, /* Intentionnaly report unhandled IDs through the SCMI return code */ *(u32 *)msg->out_msg = SCMI_PROTOCOL_ERROR; return 0; + +not_supported: + *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; + return 0; } static int sandbox_scmi_test_remove(struct udevice *dev) diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c index facb5b06ffb5..0519cf889aa9 100644 --- a/drivers/firmware/scmi/sandbox-scmi_devices.c +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c @@ -62,12 +62,13 @@ static int sandbox_scmi_devices_remove(struct udevice *dev) if (!devices) return 0; - for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) { - int ret2 = reset_free(devices->reset + n); + if (IS_ENABLED(CONFIG_RESET_SCMI)) + for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) { + int ret2 = reset_free(devices->reset + n); - if (ret2 && !ret) - ret = ret2; - } + if (ret2 && !ret) + ret = ret2; + } return ret; } @@ -89,39 +90,53 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) .regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT, }; - ret = power_domain_get_by_index(dev, priv->devices.pwdom, 0); - if (ret) { - dev_err(dev, "%s: Failed on power domain\n", __func__); - return ret; - } - - for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { - ret = clk_get_by_index(dev, n, priv->devices.clk + n); + if (IS_ENABLED(CONFIG_SCMI_
[PATCH 3/5] cmd: add scmi command for SCMI firmware
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 Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere --- v3 * describe that arguments are in hex at a help message * modify the code for dynamically allocated agent names v2 * remove sub command category, 'scmi base', for simplicity --- cmd/Kconfig | 9 ++ cmd/Makefile | 1 + cmd/scmi.c | 335 +++ 3 files changed, 345 insertions(+) create mode 100644 cmd/scmi.c diff --git a/cmd/Kconfig b/cmd/Kconfig index 205df2f1fb65..c940051eba91 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2550,6 +2550,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 9a6790cc1708..320f0b5266eb 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -159,6 +159,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 ..f8f54f84cff8 --- /dev/null +++ b/cmd/scmi.c @@ -0,0 +1,335 @@ +// 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, *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", scmi_num_agents(agent)); + for (i = 0; i < scmi_num_agents(agent); i++) { + ret = scmi_base_discover_agent(base_proto, i, &agent_id, + &agent_name); + if (ret) { + if (ret != -EOPNOTSUPP) + printf("base_discover_agent() failed for id: %d (%d)\n", + i, ret); + break; + } + printf("%c%2d: %s\n", i == scmi_agent_id(agent) ? '>' : ' ', + i, agent_n
[PATCH 4/5] doc: cmd: add documentation for scmi
This is a help text for scmi command. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere --- v6 * add the manual to doc/usage/index.rst v4 * s/tranport/transport/ v2 * add more descriptions about SCMI --- doc/usage/cmd/scmi.rst | 126 + doc/usage/index.rst| 1 + 2 files changed, 127 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 ..9ea7e0e41dad --- /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 transport 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 + + +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 diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 98b4719c4088..9a65b50aeed7 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -94,6 +94,7 @@ Shell commands cmd/saves cmd/sbi cmd/sf + cmd/scmi cmd/scp03 cmd/seama cmd/setexpr -- 2.34.1
[PATCH 5/5] test: dm: add scmi command test
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 --- v7 * make test assertions more flexible depending on the number of provided protocols v4 * move 'base'-related changes to the prior commit * add CONFIG_CMD_SCMI to sandbox_defconfig v3 * change char to u8 in vendor/agent names v2 * use helper functions, removing direct uses of ops --- configs/sandbox_defconfig | 1 + test/dm/scmi.c| 81 +++ 2 files changed, 82 insertions(+) diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index e3a2f9eb1708..34e3cc281d7f 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -120,6 +120,7 @@ CONFIG_CMD_REGULATOR=y CONFIG_CMD_AES=y CONFIG_CMD_TPM=y CONFIG_CMD_TPM_TEST=y +CONFIG_CMD_SCMI=y CONFIG_CMD_BTRFS=y CONFIG_CMD_CBFS=y CONFIG_CMD_CRAMFS=y diff --git a/test/dm/scmi.c b/test/dm/scmi.c index 2f63f2da16fb..2bcf7ac6fcc3 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -206,6 +207,86 @@ 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; + int num_proto = 0; + char cmd_out[30]; + + if (!IS_ENABLED(CONFIG_CMD_SCMI)) + return 0; + + /* preparation */ + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", + &agent_dev)); + ut_assertnonnull(agent_dev); + + /* +* Estimate the number of provided protocols. +* This estimation is correct as far as a corresponding +* protocol support is added to sandbox fake serer. +*/ + if (IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)) + num_proto++; + if (IS_ENABLED(CONFIG_CLK_SCMI)) + num_proto++; + if (IS_ENABLED(CONFIG_RESET_SCMI)) + num_proto++; + if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) + num_proto++; + + /* scmi info */ + ut_assertok(run_command("scmi info", 0)); + + ut_assert_nextline("SCMI device: scmi"); + snprintf(cmd_out, 30, " protocol version: 0x%x", +SCMI_BASE_PROTOCOL_VERSION); + ut_assert_nextline(cmd_out); + ut_assert_nextline(" # of agents: 2"); + ut_assert_nextline(" 0: platform"); + ut_assert_nextline("> 1: OSPM"); + snprintf(cmd_out, 30, " # of protocols: %d", num_proto); + ut_assert_nextline(cmd_out); + if (IS_ENABLED(CONFIG_SCMI_POWER_DOMAIN)) + ut_assert_nextline(" Power domain management"); + if (IS_ENABLED(CONFIG_CLK_SCMI)) + ut_assert_nextline(" Clock management"); + if (IS_ENABLED(CONFIG_RESET_SCMI)) + ut_assert_nextline(" Reset domain management"); + if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) + 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_power_domains(struct unit_test_state *uts) { struct sandbox_scmi_agent *agent; -- 2.34.1
Re: [PATCH 3/5] cmd: add scmi command for SCMI firmware
Hi Michal, On Wed, Oct 25, 2023 at 09:29:04AM +0200, Michal Simek wrote: > > > On 10/25/23 07:14, AKASHI Takahiro wrote: > > 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 > > Reviewed-by: Simon Glass > > Reviewed-by: Etienne Carriere > > --- > > v3 > > * describe that arguments are in hex at a help message > > * modify the code for dynamically allocated agent names > > v2 > > * remove sub command category, 'scmi base', for simplicity > > --- > > cmd/Kconfig | 9 ++ > > cmd/Makefile | 1 + > > cmd/scmi.c | 335 +++ > > 3 files changed, 345 insertions(+) > > create mode 100644 cmd/scmi.c > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 205df2f1fb65..c940051eba91 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -2550,6 +2550,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 > > As I said in previous email. default n should be removed. > It is default option. I see. I hope that Tom will take care of that when merging if there is no other comment. -Takahiro Akashi > You can take a look at least on this commit. > > commit b4c2c151b14b59a2403675526adf666710cade67 > Author: Michal Simek > AuthorDate: Fri Aug 27 08:48:10 2021 +0200 > Commit: Tom Rini > CommitDate: Tue Aug 31 17:47:49 2021 -0400 > > Kconfig: Remove all default n/no options > > default n/no doesn't need to be specified. It is default option anyway. > > Signed-off-by: Michal Simek > [trini: Rework FSP_USE_UPD portion] > Signed-off-by: Tom Rini > > I have also sent one more resync patch and CC you there too. > > Thanks, > Michal > > > >
[RFC 00/13] cmd: bootefi: refactor the code for bootmgr
This patch set is motivated by the discussion[1] regarding CONFIG_BOOTEFI_BOOTMGR option. At the end, bootefi.c will be decomposed into two parts, one for providing the command itself and one for implementing helper functions. EFI_LOADER will now be available without CONFIG_CMDLINE or specifically CONFIG_CMD_BOOTEFI if invoked via bootmeth/bootstd. Then, EFI_LOADER library side will be further split into two options for fine-grain control: CONFIG_EFI_BINARY_EXEC: execute UEFI binaries which are to be explicitly loaded by U-Boot's load commands/functions or other methods (like a jtag debugger?) It supports bootmeth_efi as well as "bootefi |hello"(/"bootm"?). CONFIG_EFI_BOOTMGR: provide EFI boot manger functionality It supports bootmeth_efi_mgr as well as "bootefi bootmgr". As such, We will no longer need CONFIG_BINARY_EXEC if we want to only make use of the boot manger for booting a next stage OS. Prerequisite This patch set is based on top of Simon/Tom's [2]. Patches === Patch#1-#11: I hope that those commits show step-by-step refactoring without introducing degradation. Patch#12-#13: Those are not directly related to the patch's aim, but they are necessary to compile U-Boot on sandbox (sandbox_defconfig) without CONFIG_CMDLINE. [1] https://lists.denx.de/pipermail/u-boot/2023-October/534598.html [2] origin/TEST/v4.1-tidy-up-use-of-CONFIG_CMDLINE AKASHI Takahiro (13): cmd: bootefi: unfold do_bootefi_image() cmd: bootefi: re-organize do_bootefi_image() cmd: bootefi: carve out EFI boot manager interface cmd: bootefi: carve out binary execution interface cmd: bootefi: move library interfaces under lib/efi_loader cmd: efidebug: ease efi configuration dependency bootmeth: use efi_loader interfaces instead of bootefi command efi_loader: split unrelated code from efi_bootmgr.c efi_loader: rename BOOTEFI_BOOTMGR to EFI_BOOTMGR net: tftp: remove explicit efi configuration dependency fs: remove explicit efi configuration dependency lib: uuid: move CONFIG_RANDOM_UUID block: rkmtd: select CONFIG_RANDOM_UUID explicitly boot/Kconfig | 4 +- boot/Makefile| 2 +- boot/bootm_os.c | 31 +- boot/bootmeth_efi.c | 8 +- boot/bootmeth_efi_mgr.c | 3 +- cmd/Kconfig | 28 +- cmd/bootefi.c| 658 +-- cmd/efidebug.c | 4 +- drivers/block/Kconfig| 1 + fs/fs.c | 7 +- include/efi_loader.h | 34 +- lib/Kconfig | 7 + lib/efi_loader/Kconfig | 11 +- lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_bootmgr.c | 37 ++ lib/efi_loader/efi_device_path.c | 3 +- lib/efi_loader/efi_helper.c | 486 ++- net/tftp.c | 10 +- test/boot/bootflow.c | 2 +- 19 files changed, 697 insertions(+), 641 deletions(-) -- 2.34.1
[RFC 01/13] cmd: bootefi: unfold do_bootefi_image()
Unfold do_bootefi_image() into do_bootefi() for the sake of the succeeding refactor work. Signed-off-by: AKASHI Takahiro --- cmd/bootefi.c | 101 ++ 1 file changed, 37 insertions(+), 64 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 20e5c94a33a4..1b28bf5a318d 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -425,58 +425,6 @@ static int do_efibootmgr(void) return CMD_RET_SUCCESS; } -/** - * do_bootefi_image() - execute EFI binary - * - * Set up memory image for the binary to be loaded, prepare device path, and - * then call do_bootefi_exec() to execute it. - * - * @image_opt: string with image start address - * @size_opt: string with image size or NULL - * Return: status code - */ -static int do_bootefi_image(const char *image_opt, const char *size_opt) -{ - void *image_buf; - unsigned long addr, size; - efi_status_t ret; - -#ifdef CONFIG_CMD_BOOTEFI_HELLO - if (!strcmp(image_opt, "hello")) { - image_buf = __efi_helloworld_begin; - size = __efi_helloworld_end - __efi_helloworld_begin; - efi_clear_bootdev(); - } else -#endif - { - addr = strtoul(image_opt, NULL, 16); - /* Check that a numeric value was passed */ - if (!addr) - return CMD_RET_USAGE; - image_buf = map_sysmem(addr, 0); - - if (size_opt) { - size = strtoul(size_opt, NULL, 16); - if (!size) - return CMD_RET_USAGE; - efi_clear_bootdev(); - } else { - if (image_buf != image_addr) { - log_err("No UEFI binary known at %s\n", - image_opt); - return CMD_RET_FAILURE; - } - size = image_size; - } - } - ret = efi_run_image(image_buf, size); - - if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; - - return CMD_RET_SUCCESS; -} - /** * efi_run_image() - run loaded UEFI image * @@ -648,8 +596,9 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { efi_status_t ret; - char *img_addr, *img_size, *str_copy, *pos; - void *fdt; + char *p; + void *fdt, *image_buf; + unsigned long addr, size; if (argc < 2) return CMD_RET_USAGE; @@ -684,18 +633,42 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, if (!strcmp(argv[1], "selftest")) return do_efi_selftest(); #endif - str_copy = strdup(argv[1]); - if (!str_copy) { - log_err("Out of memory\n"); - return CMD_RET_FAILURE; + +#ifdef CONFIG_CMD_BOOTEFI_HELLO + if (!strcmp(argv[1], "hello")) { + image_buf = __efi_helloworld_begin; + size = __efi_helloworld_end - __efi_helloworld_begin; + efi_clear_bootdev(); + } else +#endif + { + addr = strtoul(argv[1], NULL, 16); + /* Check that a numeric value was passed */ + if (!addr) + return CMD_RET_USAGE; + image_buf = map_sysmem(addr, 0); + + p = strchr(argv[1], ':'); + if (p) { + size = strtoul(++p, NULL, 16); + if (!size) + return CMD_RET_USAGE; + efi_clear_bootdev(); + } else { + if (image_buf != image_addr) { + log_err("No UEFI binary known at %s\n", + argv[1]); + return CMD_RET_FAILURE; + } + size = image_size; + } } - pos = str_copy; - img_addr = strsep(&pos, ":"); - img_size = strsep(&pos, ":"); - ret = do_bootefi_image(img_addr, img_size); - free(str_copy); + ret = efi_run_image(image_buf, size); - return ret; + if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; } U_BOOT_LONGHELP(bootefi, -- 2.34.1
[RFC 02/13] cmd: bootefi: re-organize do_bootefi_image()
Decompose and re-organize do_bootefi_image() into three parts for the succeeding refactor work. Signed-off-by: AKASHI Takahiro --- cmd/Kconfig | 15 ++-- cmd/bootefi.c| 82 ++-- include/efi_loader.h | 2 -- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index 0eb739203ade..825a41d68aad 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -363,9 +363,19 @@ config CMD_BOOTEFI help Boot an EFI image from memory. +if CMD_BOOTEFI +config CMD_BOOTEFI_BINARY + bool "Allow booting an EFI binary directly" + depends on BOOTEFI_BOOTMGR + default y + help + Select this option to enable direct execution of binary at 'bootefi'. + This subcommand will allow you to load the UEFI binary using + other U-Boot commands or external methods and then run it. + config CMD_BOOTEFI_BOOTMGR bool "UEFI Boot Manager command" - depends on BOOTEFI_BOOTMGR && CMD_BOOTEFI + depends on BOOTEFI_BOOTMGR default y help Select this option to enable the 'bootmgr' subcommand of 'bootefi'. @@ -374,7 +384,7 @@ config CMD_BOOTEFI_BOOTMGR config CMD_BOOTEFI_HELLO_COMPILE bool "Compile a standard EFI hello world binary for testing" - depends on CMD_BOOTEFI && !CPU_V7M + depends on !CPU_V7M default y help This compiles a standard EFI hello world application with U-Boot so @@ -396,6 +406,7 @@ config CMD_BOOTEFI_HELLO up EFI support on a new architecture. source lib/efi_selftest/Kconfig +endif config CMD_BOOTMENU bool "bootmenu" diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 1b28bf5a318d..ae00bba3b4f0 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -491,7 +491,6 @@ out: return (ret != EFI_SUCCESS) ? ret : ret2; } -#ifdef CONFIG_CMD_BOOTEFI_SELFTEST static efi_status_t bootefi_run_prepare(const char *load_options_path, struct efi_device_path *device_path, struct efi_device_path *image_path, @@ -581,7 +580,6 @@ static int do_efi_selftest(void) return ret != EFI_SUCCESS; } -#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ /** * do_bootefi() - execute `bootefi` command @@ -603,14 +601,6 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, if (argc < 2) return CMD_RET_USAGE; - /* Initialize EFI drivers */ - ret = efi_init_obj_list(); - if (ret != EFI_SUCCESS) { - log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); - return CMD_RET_FAILURE; - } - if (argc > 2) { uintptr_t fdt_addr; @@ -619,29 +609,54 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, } else { fdt = EFI_FDT_USE_INTERNAL; } - ret = efi_install_fdt(fdt); - if (ret == EFI_INVALID_PARAMETER) - return CMD_RET_USAGE; - else if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; - if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) { - if (!strcmp(argv[1], "bootmgr")) - return do_efibootmgr(); + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR) && + !strcmp(argv[1], "bootmgr")) { + /* Initialize EFI drivers */ + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); + return CMD_RET_FAILURE; + } + + ret = efi_install_fdt(fdt); + if (ret == EFI_INVALID_PARAMETER) + return CMD_RET_USAGE; + else if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + + return do_efibootmgr(); } -#ifdef CONFIG_CMD_BOOTEFI_SELFTEST - if (!strcmp(argv[1], "selftest")) + + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_SELFTEST) && + !strcmp(argv[1], "selftest")) { + /* Initialize EFI drivers */ + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); + return CMD_RET_FAILURE; + } + + ret = efi_install_fdt(fdt); + if (ret == EFI_INVALID_PARAMETER) + return CMD_RET_USAGE; + else if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + retu
[RFC 03/13] cmd: bootefi: carve out EFI boot manager interface
Carve EFI boot manager related code out of do_bootefi_image(). Signed-off-by: AKASHI Takahiro --- cmd/bootefi.c | 43 --- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index ae00bba3b4f0..899ed90f6817 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -401,28 +401,40 @@ out: } /** - * do_efibootmgr() - execute EFI boot manager + * efi_bootmgr_run() - execute EFI boot manager + * fdt:Flat device tree + * + * Invoke EFI boot manager and execute a binary depending on + * boot options. If @fdt is not NULL, it will be passed to + * the executed binary. * * Return: status code */ -static int do_efibootmgr(void) +static efi_status_t efi_bootmgr_run(void *fdt) { efi_handle_t handle; - efi_status_t ret; void *load_options; + efi_status_t ret; - ret = efi_bootmgr_load(&handle, &load_options); + /* Initialize EFI drivers */ + ret = efi_init_obj_list(); if (ret != EFI_SUCCESS) { - log_notice("EFI boot manager: Cannot load any image\n"); + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); return CMD_RET_FAILURE; } - ret = do_bootefi_exec(handle, load_options); - + ret = efi_install_fdt(fdt); if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; + return ret; - return CMD_RET_SUCCESS; + ret = efi_bootmgr_load(&handle, &load_options); + if (ret != EFI_SUCCESS) { + log_notice("EFI boot manager: Cannot load any image\n"); + return ret; + } + + return do_bootefi_exec(handle, load_options); } /** @@ -612,21 +624,14 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR) && !strcmp(argv[1], "bootmgr")) { - /* Initialize EFI drivers */ - ret = efi_init_obj_list(); - if (ret != EFI_SUCCESS) { - log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); - return CMD_RET_FAILURE; - } + ret = efi_bootmgr_run(fdt); - ret = efi_install_fdt(fdt); if (ret == EFI_INVALID_PARAMETER) return CMD_RET_USAGE; - else if (ret != EFI_SUCCESS) + else if (ret) return CMD_RET_FAILURE; - return do_efibootmgr(); + return CMD_RET_SUCCESS; } if (IS_ENABLED(CONFIG_CMD_BOOTEFI_SELFTEST) && -- 2.34.1
[RFC 04/13] cmd: bootefi: carve out binary execution interface
Carve binary execution code out of do_bootefi_image(). Signed-off-by: AKASHI Takahiro --- cmd/bootefi.c | 46 -- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 899ed90f6817..8b0bd07f1ff8 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -503,6 +503,36 @@ out: return (ret != EFI_SUCCESS) ? ret : ret2; } +/** + * efi_binary_run() - run loaded UEFI image + * + * @image: memory address of the UEFI image + * @size: size of the UEFI image + * + * Execute an EFI binary image loaded at @image. + * @size may be zero if the binary is loaded with U-Boot load command. + * + * Return: status code + */ +static efi_status_t efi_binary_run(void *image, size_t size, void *fdt) +{ + efi_status_t ret; + + /* Initialize EFI drivers */ + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); + return ret; + } + + ret = efi_install_fdt(fdt); + if (ret != EFI_SUCCESS) + return ret; + + return efi_run_image(image, size); +} + static efi_status_t bootefi_run_prepare(const char *load_options_path, struct efi_device_path *device_path, struct efi_device_path *image_path, @@ -684,23 +714,11 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, } } - /* Initialize EFI drivers */ - ret = efi_init_obj_list(); - if (ret != EFI_SUCCESS) { - log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); - return CMD_RET_FAILURE; - } + ret = efi_binary_run(image_buf, size, fdt); - ret = efi_install_fdt(fdt); if (ret == EFI_INVALID_PARAMETER) return CMD_RET_USAGE; - else if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; - - ret = efi_run_image(image_buf, size); - - if (ret != EFI_SUCCESS) + else if (ret) return CMD_RET_FAILURE; return CMD_RET_SUCCESS; -- 2.34.1
[RFC 06/13] cmd: efidebug: ease efi configuration dependency
Now it is clear that the command actually depends on interfaces, not "bootefi bootmgr" command. Signed-off-by: AKASHI Takahiro --- cmd/efidebug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 201531ac19fc..c2b2b074e094 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1335,7 +1335,7 @@ static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, } static struct cmd_tbl cmd_efidebug_test_sub[] = { -#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR +#ifdef CONFIG_BOOTEFI_BOOTMGR U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr, "", ""), #endif @@ -1526,7 +1526,7 @@ U_BOOT_LONGHELP(efidebug, " - show UEFI memory map\n" "efidebug tables\n" " - show UEFI configuration tables\n" -#ifdef CONFIG_CMD_BOOTEFI_BOOTMGR +#ifdef CONFIG_BOOTEFI_BOOTMGR "efidebug test bootmgr\n" " - run simple bootmgr for test\n" #endif -- 2.34.1
[RFC 07/13] bootmeth: use efi_loader interfaces instead of bootefi command
Now that efi_loader subsystem provides interfaces that are equivalent with bootefi command, we can replace command invocations with APIs. Signed-off-by: AKASHI Takahiro --- boot/Kconfig| 4 ++-- boot/Makefile | 2 +- boot/bootm_os.c | 31 +++ boot/bootmeth_efi.c | 8 +--- boot/bootmeth_efi_mgr.c | 3 ++- cmd/Kconfig | 2 +- test/boot/bootflow.c| 2 +- 7 files changed, 15 insertions(+), 37 deletions(-) diff --git a/boot/Kconfig b/boot/Kconfig index fabf6fec2195..a441fac8ade1 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -511,7 +511,7 @@ config BOOTMETH_EXTLINUX_PXE config BOOTMETH_EFILOADER bool "Bootdev support for EFI boot" - depends on CMD_BOOTEFI + depends on BOOTEFI_BOOTMGR default y help Enables support for EFI boot using bootdevs. This makes the @@ -546,7 +546,7 @@ config BOOTMETH_DISTRO select BOOTMETH_SCRIPT if CMDLINE # E.g. Armbian uses scripts select BOOTMETH_EXTLINUX # E.g. Debian uses these select BOOTMETH_EXTLINUX_PXE if CMD_PXE && CMD_NET && DM_ETH - select BOOTMETH_EFILOADER if CMD_BOOTEFI # E.g. Ubuntu uses this + select BOOTMETH_EFILOADER if BOOTEFI_BOOTMGR # E.g. Ubuntu uses this config SPL_BOOTMETH_VBE bool "Bootdev support for Verified Boot for Embedded (SPL)" diff --git a/boot/Makefile b/boot/Makefile index 3fd048bb41ab..4eaa5eab4b77 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_CROS) += bootm.o bootm_os.o bootmeth_cros.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL -obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o +obj-$(CONFIG_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o obj-$(CONFIG_$(SPL_TPL_)EXPO) += bootflow_menu.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o diff --git a/boot/bootm_os.c b/boot/bootm_os.c index 9c035b5be886..029baac478ae 100644 --- a/boot/bootm_os.c +++ b/boot/bootm_os.c @@ -494,7 +494,6 @@ static int do_bootm_efi(int flag, int argc, char *const argv[], struct bootm_headers *images) { int ret; - efi_status_t efi_ret; void *image_buf; if (flag != BOOTM_STATE_OS_GO) @@ -505,37 +504,21 @@ static int do_bootm_efi(int flag, int argc, char *const argv[], if (ret) return ret; - /* Initialize EFI drivers */ - efi_ret = efi_init_obj_list(); - if (efi_ret != EFI_SUCCESS) { - printf("## Failed to initialize UEFI sub-system: r = %lu\n", - efi_ret & ~EFI_ERROR_MASK); - return 1; - } + /* We expect to return */ + images->os.type = IH_TYPE_STANDALONE; - /* Install device tree */ - efi_ret = efi_install_fdt(images->ft_len - ? images->ft_addr : EFI_FDT_USE_INTERNAL); - if (efi_ret != EFI_SUCCESS) { - printf("## Failed to install device tree: r = %lu\n", - efi_ret & ~EFI_ERROR_MASK); - return 1; - } + image_buf = map_sysmem(images->ep, images->os.image_len); /* Run EFI image */ printf("## Transferring control to EFI (at address %08lx) ...\n", images->ep); bootstage_mark(BOOTSTAGE_ID_RUN_OS); - /* We expect to return */ - images->os.type = IH_TYPE_STANDALONE; - - image_buf = map_sysmem(images->ep, images->os.image_len); + ret = efi_binary_run(image_buf, images->os.image_len, +images->ft_len +? images->ft_addr : EFI_FDT_USE_INTERNAL); - efi_ret = efi_run_image(image_buf, images->os.image_len); - if (efi_ret != EFI_SUCCESS) - return 1; - return 0; + return ret; } #endif diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index ae936c8daa18..2a9f29f9db5a 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -412,7 +412,6 @@ static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow) static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) { ulong kernel, fdt; - char cmd[50]; int ret; kernel = env_get_hex("kernel_addr_r", 0); @@ -441,12 +440,7 @@ static int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) fdt = env_get_hex("fdt_addr_r", 0); } - /* -* At some point we can add a real interface to bootefi so we can call -* this directly. For now, go through the CLI, like distro boot. -*/ - snprintf(cmd, sizeof(cmd), "bootefi %lx %lx",
[RFC 05/13] cmd: bootefi: move library interfaces under lib/efi_loader
In the prior commits, interfaces for executing EFI binary or boot manager were carved out. Move them under efi_loader directory so that they can be called from other places without depending on bootefi command. Signed-off-by: AKASHI Takahiro --- cmd/bootefi.c| 546 ++- include/efi_loader.h | 10 + lib/efi_loader/efi_bootmgr.c | 517 + 3 files changed, 551 insertions(+), 522 deletions(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 8b0bd07f1ff8..9cf9027bf409 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -7,531 +7,22 @@ #define LOG_CATEGORY LOGC_EFI -#include -#include -#include #include -#include +#include #include -#include -#include -#include -#include +#include #include #include -#include -#include -#include #include -#include +#include #include -#include +#include +#include DECLARE_GLOBAL_DATA_PTR; -static struct efi_device_path *bootefi_image_path; -static struct efi_device_path *bootefi_device_path; -static void *image_addr; -static size_t image_size; - -/** - * efi_get_image_parameters() - return image parameters - * - * @img_addr: address of loaded image in memory - * @img_size: size of loaded image - */ -void efi_get_image_parameters(void **img_addr, size_t *img_size) -{ - *img_addr = image_addr; - *img_size = image_size; -} - -/** - * efi_clear_bootdev() - clear boot device - */ -static void efi_clear_bootdev(void) -{ - efi_free_pool(bootefi_device_path); - efi_free_pool(bootefi_image_path); - bootefi_device_path = NULL; - bootefi_image_path = NULL; - image_addr = NULL; - image_size = 0; -} - -/** - * efi_set_bootdev() - set boot device - * - * This function is called when a file is loaded, e.g. via the 'load' command. - * We use the path to this file to inform the UEFI binary about the boot device. - * - * @dev: device, e.g. "MMC" - * @devnr: number of the device, e.g. "1:2" - * @path: path to file loaded - * @buffer:buffer with file loaded - * @buffer_size: size of file loaded - */ -void efi_set_bootdev(const char *dev, const char *devnr, const char *path, -void *buffer, size_t buffer_size) -{ - struct efi_device_path *device, *image; - efi_status_t ret; - - log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev, - devnr, path, buffer, buffer_size); - - /* Forget overwritten image */ - if (buffer + buffer_size >= image_addr && - image_addr + image_size >= buffer) - efi_clear_bootdev(); - - /* Remember only PE-COFF and FIT images */ - if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) { - if (IS_ENABLED(CONFIG_FIT) && - !fit_check_format(buffer, IMAGE_SIZE_INVAL)) { - /* -* FIT images of type EFI_OS are started via command -* bootm. We should not use their boot device with the -* bootefi command. -*/ - buffer = 0; - buffer_size = 0; - } else { - log_debug("- not remembering image\n"); - return; - } - } - - /* efi_set_bootdev() is typically called repeatedly, recover memory */ - efi_clear_bootdev(); - - image_addr = buffer; - image_size = buffer_size; - - ret = efi_dp_from_name(dev, devnr, path, &device, &image); - if (ret == EFI_SUCCESS) { - bootefi_device_path = device; - if (image) { - /* FIXME: image should not contain device */ - struct efi_device_path *image_tmp = image; - - efi_dp_split_file_path(image, &device, &image); - efi_free_pool(image_tmp); - } - bootefi_image_path = image; - log_debug("- boot device %pD\n", device); - if (image) - log_debug("- image %pD\n", image); - } else { - log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); - efi_clear_bootdev(); - } -} - -/** - * efi_env_set_load_options() - set load options from environment variable - * - * @handle:the image handle - * @env_var: name of the environment variable - * @load_options: pointer to load options (output) - * Return: status code - */ -static efi_status_t efi_env_set_load_options(efi_handle_t handle, -const char *env_var, -u16 **load_options) -{ - const
[RFC 08/13] efi_loader: split unrelated code from efi_bootmgr.c
Some code moved from cmd/bootefi.c is actually necessary only for "bootefi " command (starting an image manually loaded by a user using U-Boot load commands or other methods (like JTAG debugger). The code will never been opted out as unused code by a compiler which doesn't know how EFI boot manager is implemented. So introduce a new configuration, CONFIG_EFI_BINARY_EXEC, to enforce theem opted out explicitly. Signed-off-by: AKASHI Takahiro --- boot/Kconfig | 4 +- cmd/Kconfig | 6 +- include/efi_loader.h | 28 +- lib/efi_loader/Kconfig | 9 + lib/efi_loader/efi_bootmgr.c | 480 -- lib/efi_loader/efi_device_path.c | 3 +- lib/efi_loader/efi_helper.c | 486 ++- 7 files changed, 516 insertions(+), 500 deletions(-) diff --git a/boot/Kconfig b/boot/Kconfig index a441fac8ade1..d371d0a25962 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -511,7 +511,7 @@ config BOOTMETH_EXTLINUX_PXE config BOOTMETH_EFILOADER bool "Bootdev support for EFI boot" - depends on BOOTEFI_BOOTMGR + depends on EFI_BINARY_EXEC default y help Enables support for EFI boot using bootdevs. This makes the @@ -546,7 +546,7 @@ config BOOTMETH_DISTRO select BOOTMETH_SCRIPT if CMDLINE # E.g. Armbian uses scripts select BOOTMETH_EXTLINUX # E.g. Debian uses these select BOOTMETH_EXTLINUX_PXE if CMD_PXE && CMD_NET && DM_ETH - select BOOTMETH_EFILOADER if BOOTEFI_BOOTMGR # E.g. Ubuntu uses this + select BOOTMETH_EFILOADER if EFI_BINARY_EXEC # E.g. Ubuntu uses this config SPL_BOOTMETH_VBE bool "Bootdev support for Verified Boot for Embedded (SPL)" diff --git a/cmd/Kconfig b/cmd/Kconfig index 81e959c96207..bf16fad04d37 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -274,7 +274,7 @@ config CMD_BOOTMETH config BOOTM_EFI bool "Support booting UEFI FIT images" - depends on BOOTEFI_BOOTMGR && CMD_BOOTM && FIT + depends on EFI_BINARY_EXEC && CMD_BOOTM && FIT default y help Support booting UEFI FIT images via the bootm command. @@ -366,7 +366,7 @@ config CMD_BOOTEFI if CMD_BOOTEFI config CMD_BOOTEFI_BINARY bool "Allow booting an EFI binary directly" - depends on BOOTEFI_BOOTMGR + depends on EFI_BINARY_EXEC default y help Select this option to enable direct execution of binary at 'bootefi'. @@ -397,7 +397,7 @@ config CMD_BOOTEFI_HELLO_COMPILE config CMD_BOOTEFI_HELLO bool "Allow booting a standard EFI hello world for testing" - depends on CMD_BOOTEFI_HELLO_COMPILE + depends on CMD_BOOTEFI_BINARY && CMD_BOOTEFI_HELLO_COMPILE default y if CMD_BOOTEFI_SELFTEST help This adds a standard EFI hello world application to U-Boot so that diff --git a/include/efi_loader.h b/include/efi_loader.h index 031a8f76846a..e9bc2f540cc8 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -91,11 +91,7 @@ efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len); * back to u-boot world */ void efi_restore_gd(void); -/* Call this to unset the current device name */ -void efi_clear_bootdev(void); -/* Call this to set the current device name */ -void efi_set_bootdev(const char *dev, const char *devnr, const char *path, -void *buffer, size_t buffer_size); + /* Called by networking code to memorize the dhcp ack package */ void efi_net_set_dhcp_ack(void *pkt, int len); /* Print information about all loaded images */ @@ -117,10 +113,6 @@ static inline efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len) /* No loader configured, stub out EFI_ENTRY */ static inline void efi_restore_gd(void) { } -static inline void efi_clear_bootdev(void) { } -static inline void efi_set_bootdev(const char *dev, const char *devnr, - const char *path, void *buffer, - size_t buffer_size) { } static inline void efi_net_set_dhcp_ack(void *pkt, int len) { } static inline void efi_print_image_infos(void *pc) { } static inline efi_status_t efi_launch_capsules(void) @@ -130,6 +122,20 @@ static inline efi_status_t efi_launch_capsules(void) #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */ +#if CONFIG_IS_ENABLED(EFI_BINARY_EXEC) +/* Call this to unset the current device name */ +void efi_clear_bootdev(void); +/* Call this to set the current device name */ +void efi_set_bootdev(const char *dev, const char *devnr, const char *path, +void *buffer, size_t buffer_size); +#else +static inline void efi_clear_bootdev(void) { } + +static inline void efi_set_bootdev(const char *dev, const char *devnr, + const char *path, void *buffer, +
[RFC 09/13] efi_loader: rename BOOTEFI_BOOTMGR to EFI_BOOTMGR
At this point, EFI boot manager interfaces is fully independent from bootefi command. So just rename the configuration parameter. Signed-off-by: AKASHI Takahiro --- boot/Makefile | 2 +- cmd/Kconfig | 4 ++-- cmd/efidebug.c | 4 ++-- lib/efi_loader/Kconfig | 2 +- lib/efi_loader/Makefile | 2 +- test/boot/bootflow.c| 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/boot/Makefile b/boot/Makefile index 4eaa5eab4b77..48d74c67d680 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -32,7 +32,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_CROS) += bootm.o bootm_os.o bootmeth_cros.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL -obj-$(CONFIG_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o +obj-$(CONFIG_EFI_BOOTMGR) += bootmeth_efi_mgr.o obj-$(CONFIG_$(SPL_TPL_)EXPO) += bootflow_menu.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o diff --git a/cmd/Kconfig b/cmd/Kconfig index bf16fad04d37..3a8483f7d042 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -375,7 +375,7 @@ config CMD_BOOTEFI_BINARY config CMD_BOOTEFI_BOOTMGR bool "UEFI Boot Manager command" - depends on BOOTEFI_BOOTMGR + depends on EFI_BOOTMGR default y help Select this option to enable the 'bootmgr' subcommand of 'bootefi'. @@ -2122,7 +2122,7 @@ config CMD_EFIDEBUG config CMD_EFICONFIG bool "eficonfig - provide menu-driven uefi variables maintenance interface" default y if !HAS_BOARD_SIZE_LIMIT - depends on BOOTEFI_BOOTMGR + depends on EFI_BOOTMGR select MENU help Enable the 'eficonfig' command which provides the menu-driven UEFI diff --git a/cmd/efidebug.c b/cmd/efidebug.c index c2b2b074e094..7ba2331ad19f 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -1335,7 +1335,7 @@ static __maybe_unused int do_efi_test_bootmgr(struct cmd_tbl *cmdtp, int flag, } static struct cmd_tbl cmd_efidebug_test_sub[] = { -#ifdef CONFIG_BOOTEFI_BOOTMGR +#ifdef CONFIG_EFI_BOOTMGR U_BOOT_CMD_MKENT(bootmgr, CONFIG_SYS_MAXARGS, 1, do_efi_test_bootmgr, "", ""), #endif @@ -1526,7 +1526,7 @@ U_BOOT_LONGHELP(efidebug, " - show UEFI memory map\n" "efidebug tables\n" " - show UEFI configuration tables\n" -#ifdef CONFIG_BOOTEFI_BOOTMGR +#ifdef CONFIG_EFI_BOOTMGR "efidebug test bootmgr\n" " - run simple bootmgr for test\n" #endif diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 987a990509f3..27d3f52897a9 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -41,7 +41,7 @@ config EFI_BINARY_EXEC You may enable CMD_BOOTEFI_BINARY so that you can use bootefi command to do that. -config BOOTEFI_BOOTMGR +config EFI_BOOTMGR bool "UEFI Boot Manager" default y select BOOTMETH_GLOBAL if BOOTSTD diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 0a2cb6e3c476..f882474bba6f 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -42,7 +42,7 @@ targets += initrddump.o endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o -obj-$(CONFIG_BOOTEFI_BOOTMGR) += efi_bootmgr.o +obj-$(CONFIG_EFI_BOOTMGR) += efi_bootmgr.o obj-y += efi_boottime.o obj-y += efi_helper.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 47c552a94165..7eafdc79de3b 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -374,7 +374,7 @@ static int bootflow_system(struct unit_test_state *uts) { struct udevice *bootstd, *dev; - if (!IS_ENABLED(CONFIG_BOOTEFI_BOOTMGR)) + if (!IS_ENABLED(CONFIG_EFI_BOOTMGR)) return -EAGAIN; ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_efi_mgr), -- 2.34.1
[RFC 10/13] net: tftp: remove explicit efi configuration dependency
Now it is clear that the feature actually depends on efi interfaces, not "bootefi" command. efi_set_bootdev() will automatically be nullified if necessary efi component is disabled. Signed-off-by: AKASHI Takahiro --- net/tftp.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index 88e71e67de35..2e335413492b 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -302,12 +302,10 @@ static void tftp_complete(void) time_start * 1000, "/s"); } puts("\ndone\n"); - if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) { - if (!tftp_put_active) - efi_set_bootdev("Net", "", tftp_filename, - map_sysmem(tftp_load_addr, 0), - net_boot_file_size); - } + if (!tftp_put_active) + efi_set_bootdev("Net", "", tftp_filename, + map_sysmem(tftp_load_addr, 0), + net_boot_file_size); net_set_state(NETLOOP_SUCCESS); } -- 2.34.1
[RFC 11/13] fs: remove explicit efi configuration dependency
Now it is clear that the feature actually depends on efi interfaces, not "bootefi" command. efi_set_bootdev() will automatically be nullified if necessary efi component is disabled. Signed-off-by: AKASHI Takahiro --- fs/fs.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 4cb4310c9cc2..70cdb594c4c8 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -791,10 +791,9 @@ int do_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], return 1; } - if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) - efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "", - (argc > 4) ? argv[4] : "", map_sysmem(addr, 0), - len_read); + efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "", + (argc > 4) ? argv[4] : "", map_sysmem(addr, 0), + len_read); printf("%llu bytes read in %lu ms", len_read, time); if (time > 0) { -- 2.34.1
[RFC 12/13] lib: uuid: move CONFIG_RANDOM_UUID
This option is independent from any commands and should be managed under lib. For instance, drivers/block/rkmtd.c is a user. It would be better to remove this configuration. Signed-off-by: AKASHI Takahiro --- cmd/Kconfig | 7 --- lib/Kconfig | 7 +++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index 3a8483f7d042..c42745d06b39 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1143,13 +1143,6 @@ config CMD_GPT Enable the 'gpt' command to ready and write GPT style partition tables. -config RANDOM_UUID - bool "GPT Random UUID generation" - select LIB_UUID - help - Enable the generation of partitions with random UUIDs if none - are provided. - config CMD_GPT_RENAME bool "GPT partition renaming commands" depends on CMD_GPT diff --git a/lib/Kconfig b/lib/Kconfig index f6ca559897e7..b6d580c30615 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -74,6 +74,13 @@ config HAVE_PRIVATE_LIBGCC config LIB_UUID bool +config RANDOM_UUID + bool "GPT Random UUID generation" + select LIB_UUID + help + Enable the generation of partitions with random UUIDs if none + are provided. + config SPL_LIB_UUID depends on SPL bool -- 2.34.1
[RFC 13/13] block: rkmtd: select CONFIG_RANDOM_UUID explicitly
This option is necessary to compile any way. Signed-off-by: AKASHI Takahiro --- drivers/block/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 048a6caef00f..5cda21551043 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -265,6 +265,7 @@ config SYS_64BIT_LBA config RKMTD bool "Rockchip rkmtd virtual block device" + imply RANDOM_UUID help Enable "rkmtd" class and driver to create a virtual block device to transfer Rockchip boot block data to and from NAND with block -- 2.34.1
Re: [RFC 11/13] fs: remove explicit efi configuration dependency
On Thu, Oct 26, 2023 at 09:58:53AM +0200, Heinrich Schuchardt wrote: > > > Am 26. Oktober 2023 07:30:50 MESZ schrieb AKASHI Takahiro > : > >Now it is clear that the feature actually depends on efi interfaces, > >not "bootefi" command. efi_set_bootdev() will automatically be nullified > >if necessary efi component is disabled. > > > >Signed-off-by: AKASHI Takahiro > >--- > > fs/fs.c | 7 +++ > > 1 file changed, 3 insertions(+), 4 deletions(-) > > > >diff --git a/fs/fs.c b/fs/fs.c > >index 4cb4310c9cc2..70cdb594c4c8 100644 > >--- a/fs/fs.c > >+++ b/fs/fs.c > >@@ -791,10 +791,9 @@ int do_load(struct cmd_tbl *cmdtp, int flag, int argc, > >char *const argv[], > > return 1; > > } > > > >-if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) > >-efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "", > >-(argc > 4) ? argv[4] : "", map_sysmem(addr, 0), > >-len_read); > >+efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "", > > This function should not exist for CONFIG_EFI_LOADER=n. There are other > places where the function is invoked. Please, review all of them. Please go through the whole patch set, especially patch#8 "efi_loader: split unrelated code from efi_bootmgr.c". efi_[set|clear]_bootdev() will be nullified if not necessary. -Takahiro Akashi > Best regards > > Heinrich > > > >+(argc > 4) ? argv[4] : "", map_sysmem(addr, 0), > >+len_read); > > > > printf("%llu bytes read in %lu ms", len_read, time); > > if (time > 0) {
Re: [RFC 01/13] cmd: bootefi: unfold do_bootefi_image()
On Thu, Oct 26, 2023 at 01:01:52PM +0200, Heinrich Schuchardt wrote: > On 10/26/23 07:30, AKASHI Takahiro wrote: > > Unfold do_bootefi_image() into do_bootefi() for the sake of the succeeding > > refactor work. > > > > Signed-off-by: AKASHI Takahiro > > --- > > cmd/bootefi.c | 101 ++ > > 1 file changed, 37 insertions(+), 64 deletions(-) > > > > diff --git a/cmd/bootefi.c b/cmd/bootefi.c > > index 20e5c94a33a4..1b28bf5a318d 100644 > > --- a/cmd/bootefi.c > > +++ b/cmd/bootefi.c > > @@ -425,58 +425,6 @@ static int do_efibootmgr(void) > > return CMD_RET_SUCCESS; > > } > > > > -/** > > - * do_bootefi_image() - execute EFI binary > > - * > > - * Set up memory image for the binary to be loaded, prepare device path, > > and > > - * then call do_bootefi_exec() to execute it. > > - * > > - * @image_opt: string with image start address > > - * @size_opt: string with image size or NULL > > - * Return: status code > > - */ > > -static int do_bootefi_image(const char *image_opt, const char *size_opt) > > -{ > > - void *image_buf; > > - unsigned long addr, size; > > - efi_status_t ret; > > - > > -#ifdef CONFIG_CMD_BOOTEFI_HELLO > > - if (!strcmp(image_opt, "hello")) { > > - image_buf = __efi_helloworld_begin; > > - size = __efi_helloworld_end - __efi_helloworld_begin; > > - efi_clear_bootdev(); > > - } else > > -#endif > > - { > > - addr = strtoul(image_opt, NULL, 16); > > - /* Check that a numeric value was passed */ > > - if (!addr) > > - return CMD_RET_USAGE; > > - image_buf = map_sysmem(addr, 0); > > - > > - if (size_opt) { > > - size = strtoul(size_opt, NULL, 16); > > - if (!size) > > - return CMD_RET_USAGE; > > - efi_clear_bootdev(); > > - } else { > > - if (image_buf != image_addr) { > > - log_err("No UEFI binary known at %s\n", > > - image_opt); > > - return CMD_RET_FAILURE; > > - } > > - size = image_size; > > - } > > - } > > - ret = efi_run_image(image_buf, size); > > - > > - if (ret != EFI_SUCCESS) > > - return CMD_RET_FAILURE; > > - > > - return CMD_RET_SUCCESS; > > -} > > - > > /** > >* efi_run_image() - run loaded UEFI image > >* > > @@ -648,8 +596,9 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, > > int argc, > > char *const argv[]) > > { > > efi_status_t ret; > > - char *img_addr, *img_size, *str_copy, *pos; > > - void *fdt; > > + char *p; > > + void *fdt, *image_buf; > > + unsigned long addr, size; > > > > if (argc < 2) > > return CMD_RET_USAGE; > > @@ -684,18 +633,42 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int > > flag, int argc, > > if (!strcmp(argv[1], "selftest")) > > return do_efi_selftest(); > > #endif > > - str_copy = strdup(argv[1]); > > - if (!str_copy) { > > - log_err("Out of memory\n"); > > - return CMD_RET_FAILURE; > > + > > +#ifdef CONFIG_CMD_BOOTEFI_HELLO > > I would prefer a normal if and let the linker sort it out. Here I focused on simply unfolding("moving") the function, keeping the code as same as possible. Any how the code is in a tentative form at this point and will be reshaped in later patches, using IS_ENABLED(). Please look at the final code after applying the whole series. -Takahiro Akashi > Otherwise looks good to me. > > Best regards > > Heinrich > > > + if (!strcmp(argv[1], "hello")) { > > + image_buf = __efi_helloworld_begin; > > + size = __efi_helloworld_end - __efi_helloworld_begin; > > + efi_clear_bootdev(); > > + } else > > +#endif > > + { > > + addr = strtoul(argv[1], NULL, 16); > > + /* Check that a numeric value was passed */ > > + if (!addr) > > + return CMD_RET_USAGE; > > + image_buf = map_sysmem(addr, 0); > > + > > + p = strchr(argv[1], ':'
Re: [RFC 02/13] cmd: bootefi: re-organize do_bootefi_image()
On Thu, Oct 26, 2023 at 12:44:00PM +0200, Heinrich Schuchardt wrote: > On 10/26/23 07:30, AKASHI Takahiro wrote: > > Decompose and re-organize do_bootefi_image() into three parts for > > the succeeding refactor work. > > > > Signed-off-by: AKASHI Takahiro > > --- > > cmd/Kconfig | 15 ++-- > > cmd/bootefi.c| 82 ++-- > > include/efi_loader.h | 2 -- > > 3 files changed, 69 insertions(+), 30 deletions(-) > > > > diff --git a/cmd/Kconfig b/cmd/Kconfig > > index 0eb739203ade..825a41d68aad 100644 > > --- a/cmd/Kconfig > > +++ b/cmd/Kconfig > > @@ -363,9 +363,19 @@ config CMD_BOOTEFI > > help > > Boot an EFI image from memory. > > > > +if CMD_BOOTEFI > > +config CMD_BOOTEFI_BINARY > > + bool "Allow booting an EFI binary directly" > > + depends on BOOTEFI_BOOTMGR > > + default y > > + help > > + Select this option to enable direct execution of binary at 'bootefi'. > > + This subcommand will allow you to load the UEFI binary using > > + other U-Boot commands or external methods and then run isince 2021. t. > > + > > config CMD_BOOTEFI_BOOTMGR > > This symbol is in lib/efi_loader/Kconfig: > lib/efi_loader/Kconfig:35:config CMD_BOOTEFI_BOOTMGR In the cover letter, I mentioned that the RFC was based on Tom's branch. > > Please, rebase your series on origin/master. If you agree to my idea in this whole series, I will re-post a new version, rebasing it on Tom's "-next" branch with CONFIG_CMDLINE tweaks. So please review other commits as well. Thanks, -Takahiro Akashi > Best regards > > Heinrich > > > bool "UEFI Boot Manager command" > > - depends on BOOTEFI_BOOTMGR && CMD_BOOTEFI > > + depends on BOOTEFI_BOOTMGR > > default y > > help > > Select this option to enable the 'bootmgr' subcommand of 'bootefi'. > > @@ -374,7 +384,7 @@ config CMD_BOOTEFI_BOOTMGR > > > > config CMD_BOOTEFI_HELLO_COMPILE > > bool "Compile a standard EFI hello world binary for testing" > > - depends on CMD_BOOTEFI && !CPU_V7M > > + depends on !CPU_V7M > > default y > > help > > This compiles a standard EFI hello world application with U-Boot so > > @@ -396,6 +406,7 @@ config CMD_BOOTEFI_HELLO > > up EFI support on a new architecture. > > > > source lib/efi_selftest/Kconfig > > +endif > > > > config CMD_BOOTMENU > > bool "bootmenu" > > diff --git a/cmd/bootefi.c b/cmd/bootefi.c > > index 1b28bf5a318d..ae00bba3b4f0 100644 > > --- a/cmd/bootefi.c > > +++ b/cmd/bootefi.c > > @@ -491,7 +491,6 @@ out: > > return (ret != EFI_SUCCESS) ? ret : ret2; > > } > > > > -#ifdef CONFIG_CMD_BOOTEFI_SELFTEST > > static efi_status_t bootefi_run_prepare(const char *load_options_path, > > struct efi_device_path *device_path, > > struct efi_device_path *image_path, > > @@ -581,7 +580,6 @@ static int do_efi_selftest(void) > > > > return ret != EFI_SUCCESS; > > } > > -#endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ > > > > /** > >* do_bootefi() - execute `bootefi` command > > @@ -603,14 +601,6 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, > > int argc, > > if (argc < 2) > > return CMD_RET_USAGE; > > > > - /* Initialize EFI drivers */ > > - ret = efi_init_obj_list(); > > - if (ret != EFI_SUCCESS) { > > - log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", > > - ret & ~EFI_ERROR_MASK); > > - return CMD_RET_FAILURE; > > - } > > - > > if (argc > 2) { > > uintptr_t fdt_addr; > > > > @@ -619,29 +609,54 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int > > flag, int argc, > > } else { > > fdt = EFI_FDT_USE_INTERNAL; > > } > > - ret = efi_install_fdt(fdt); > > - if (ret == EFI_INVALID_PARAMETER) > > - return CMD_RET_USAGE; > > - else if (ret != EFI_SUCCESS) > > - return CMD_RET_FAILURE; > > > > - if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) { > > - if (!strcmp(argv[1], "bootmgr")) > > - return do_efibootmgr(); > > + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR) && > > + !strcmp(ar
Re: [RFC 11/13] fs: remove explicit efi configuration dependency
On Thu, Oct 26, 2023 at 08:47:52AM -0400, Tom Rini wrote: > On Thu, Oct 26, 2023 at 05:48:30PM +0900, AKASHI Takahiro wrote: > > On Thu, Oct 26, 2023 at 09:58:53AM +0200, Heinrich Schuchardt wrote: > > > > > > > > > Am 26. Oktober 2023 07:30:50 MESZ schrieb AKASHI Takahiro > > > : > > > >Now it is clear that the feature actually depends on efi interfaces, > > > >not "bootefi" command. efi_set_bootdev() will automatically be nullified > > > >if necessary efi component is disabled. > > > > > > > >Signed-off-by: AKASHI Takahiro > > > >--- > > > > fs/fs.c | 7 +++ > > > > 1 file changed, 3 insertions(+), 4 deletions(-) > > > > > > > >diff --git a/fs/fs.c b/fs/fs.c > > > >index 4cb4310c9cc2..70cdb594c4c8 100644 > > > >--- a/fs/fs.c > > > >+++ b/fs/fs.c > > > >@@ -791,10 +791,9 @@ int do_load(struct cmd_tbl *cmdtp, int flag, int > > > >argc, char *const argv[], > > > > return 1; > > > > } > > > > > > > >-if (IS_ENABLED(CONFIG_CMD_BOOTEFI)) > > > >-efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "", > > > >-(argc > 4) ? argv[4] : "", > > > >map_sysmem(addr, 0), > > > >-len_read); > > > >+efi_set_bootdev(argv[1], (argc > 2) ? argv[2] : "", > > > > > > This function should not exist for CONFIG_EFI_LOADER=n. There are other > > > places where the function is invoked. Please, review all of them. > > > > Please go through the whole patch set, especially patch#8 > > "efi_loader: split unrelated code from efi_bootmgr.c". > > > > efi_[set|clear]_bootdev() will be nullified if not necessary. > > In this case I think what we have here today is more readable / clearer. > We don't need empty functions as we can either do like this section of > the code does today or the linker will discard things correctly as it's > a case of funcB() calls funcA() and nothing calls funcB() so it will be > discarded. I don't know without digging through the series more what the > correct IS_ENABLED() guard should be here (and then also in patch #10). If I correctly understand your question, it is my point in this commit. I believe that a caller should not be bothered by thinking of what efi CONFIG be used for the guard. All that should be done is to just put a right hook (efi_set_bootdev() in this case) at a right place as a caller (do_load() in this case) is apparently irrelevant to UEFI subsystem. Hereafter, whatever rework may be done on UEFI side (like my refactoring here), other code won't need to be modified. If you want to rely on an intelligent linker behavior, I would suggest another approach, modifying efi_set_bootdev() as follows; efi_set_bootdev(...) { if (!IS_ENABLED(EFI_BINARY_EXEC)) return; ... } I hope it would also work. -Takahiro Akashi > > -- > Tom signature.asc Description: PGP signature
Re: [RFC 01/13] cmd: bootefi: unfold do_bootefi_image()
Hi Ilias, On Fri, Oct 27, 2023 at 03:23:07PM +0300, Ilias Apalodimas wrote: > Akashi-san > > On Fri, 27 Oct 2023 at 04:00, Tom Rini wrote: > > > > On Fri, Oct 27, 2023 at 09:25:44AM +0900, AKASHI Takahiro wrote: > > > On Thu, Oct 26, 2023 at 01:01:52PM +0200, Heinrich Schuchardt wrote: > > > > On 10/26/23 07:30, AKASHI Takahiro wrote: > > > > > Unfold do_bootefi_image() into do_bootefi() for the sake of the > > > > > succeeding > > > > > refactor work. > > > > > > > I don't disagree with the patchset, but what the patch does is pretty > obvious. Yeah, that is what I tried to do in this patch series, i.e. each step be as trivial as possible to ensure that the semantics is unchanged while the code is being morphed. > It would help a lot to briefly describe how the unfolding > process helps the refactoring. Not sure, but will add a few more words. Thanks, -Takahiro Akashi > Thanks > /Ilias > > > > > Signed-off-by: AKASHI Takahiro > > > > > --- > > > > > cmd/bootefi.c | 101 > > > > > ++ > > > > > 1 file changed, 37 insertions(+), 64 deletions(-) > > > > > > > > > > diff --git a/cmd/bootefi.c b/cmd/bootefi.c > > > > > index 20e5c94a33a4..1b28bf5a318d 100644 > > > > > --- a/cmd/bootefi.c > > > > > +++ b/cmd/bootefi.c > > > > > @@ -425,58 +425,6 @@ static int do_efibootmgr(void) > > > > > return CMD_RET_SUCCESS; > > > > > } > > > > > > > > > > -/** > > > > > - * do_bootefi_image() - execute EFI binary > > > > > - * > > > > > - * Set up memory image for the binary to be loaded, prepare device > > > > > path, and > > > > > - * then call do_bootefi_exec() to execute it. > > > > > - * > > > > > - * @image_opt: string with image start address > > > > > - * @size_opt:string with image size or NULL > > > > > - * Return: status code > > > > > - */ > > > > > -static int do_bootefi_image(const char *image_opt, const char > > > > > *size_opt) > > > > > -{ > > > > > - void *image_buf; > > > > > - unsigned long addr, size; > > > > > - efi_status_t ret; > > > > > - > > > > > -#ifdef CONFIG_CMD_BOOTEFI_HELLO > > > > > - if (!strcmp(image_opt, "hello")) { > > > > > - image_buf = __efi_helloworld_begin; > > > > > - size = __efi_helloworld_end - __efi_helloworld_begin; > > > > > - efi_clear_bootdev(); > > > > > - } else > > > > > -#endif > > > > > - { > > > > > - addr = strtoul(image_opt, NULL, 16); > > > > > - /* Check that a numeric value was passed */ > > > > > - if (!addr) > > > > > - return CMD_RET_USAGE; > > > > > - image_buf = map_sysmem(addr, 0); > > > > > - > > > > > - if (size_opt) { > > > > > - size = strtoul(size_opt, NULL, 16); > > > > > - if (!size) > > > > > - return CMD_RET_USAGE; > > > > > - efi_clear_bootdev(); > > > > > - } else { > > > > > - if (image_buf != image_addr) { > > > > > - log_err("No UEFI binary known at %s\n", > > > > > - image_opt); > > > > > - return CMD_RET_FAILURE; > > > > > - } > > > > > - size = image_size; > > > > > - } > > > > > - } > > > > > - ret = efi_run_image(image_buf, size); > > > > > - > > > > > - if (ret != EFI_SUCCESS) > > > > > - return CMD_RET_FAILURE; > > > > > - > > > > > - return CMD_RET_SUCCESS; > > > > > -} > > > > > - > > > > > /** > > > > >* efi_run_image() - run loaded UEFI image > > > > >* > > > > > @@ -648,8 +596,9 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int > > > > > flag, int argc, > > > > > char *const argv[]) > > > > > { > > > > > efi_status_t ret; > > > > > - char *img_addr, *img_size, *str_copy, *pos; > > > > > - void *fdt; > > > > > + char *p; > > > > > + void *fdt, *image_buf; > > > > > + unsigned long addr, size; > > > > > > > > > > if (argc < 2) > > > > > return CMD_RET_USAGE; > > > > > @@ -684,18 +633,42 @@ static int do_bootefi(struct cmd_tbl *cmdtp, > > > > > int flag, int argc, > > > > > if (!strcmp(argv[1], "selftest")) > > > > > return do_efi_selftest(); > > > > > #endif > > > > > - str_copy = strdup(argv[1]); > > > > > - if (!str_copy) { > > > > > - log_err("Out of memory\n"); > > > > > - return CMD_RET_FAILURE; > > > > > + > > > > > +#ifdef CONFIG_CMD_BOOTEFI_HELLO > > > > > > > > I would prefer a normal if and let the linker sort it out. > > > > > > Here I focused on simply unfolding("moving") the function, keeping the > > > code > > > as same as possible. Any how the code is in a tentative form > > > at this point and will be reshaped in later patches, using IS_ENABLED(). > > > Please look at the final code after applying the whole series. > > > > I also agree with this approach. > > > > -- > > Tom
[PATCH] cmd: dm: allow for selecting uclass and device
The output from "dm tree" or "dm uclass" is a bit annoying if the number of devices available on the system is huge. (This is especially true on sandbox when I debug some DM code.) With this patch, we can specify the uclass or the device that we are interested in in order to limit the output. For instance, => dm uclass usb uclass 121: usb 0 usb@1 @ 0bd008b0, seq 1 => dm tree usb:usb@1 Class Index Probed DriverName --- usb 0 [ ] usb_sandbox usb@1 usb_hub 0 [ ] usb_hub `-- hub usb_emul 0 [ ] usb_sandbox_hub `-- hub-emul usb_emul 1 [ ] usb_sandbox_flash |-- flash-stick@0 usb_emul 2 [ ] usb_sandbox_flash |-- flash-stick@1 usb_emul 3 [ ] usb_sandbox_flash |-- flash-stick@2 usb_emul 4 [ ] usb_sandbox_keyb `-- keyb@3 Please note that, at "dm tree", the uclass name (usb) as well as the device name (usb@1) is required. Signed-off-by: AKASHI Takahiro --- cmd/dm.c| 30 drivers/core/dump.c | 48 +++-- include/dm/util.h | 13 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/cmd/dm.c b/cmd/dm.c index 3263547cbec6..99268df2f87a 100644 --- a/cmd/dm.c +++ b/cmd/dm.c @@ -59,11 +59,20 @@ static int do_dm_dump_static_driver_info(struct cmd_tbl *cmdtp, int flag, static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - bool sort; + bool sort = false; + char *device = NULL; - sort = argc > 1 && !strcmp(argv[1], "-s"); + if (argc > 1) { + if (!strcmp(argv[1], "-s")) { + sort = true; + argc--; + argv++; + } + if (argc > 1) + device = argv[1]; + } - dm_dump_tree(sort); + dm_dump_tree(device, sort); return 0; } @@ -71,7 +80,12 @@ static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, static int do_dm_dump_uclass(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - dm_dump_uclass(); + char *uclass = NULL; + + if (argc > 1) + uclass = argv[1]; + + dm_dump_uclass(uclass); return 0; } @@ -91,8 +105,8 @@ static char dm_help_text[] = "dm drivers Dump list of drivers with uclass and instances\n" DM_MEM_HELP "dm staticDump list of drivers with static platform data\n" - "dm tree [-s] Dump tree of driver model devices (-s=sort)\n" - "dm uclassDump list of instances for each uclass" + "dm tree [-s][name] Dump tree of driver model devices (-s=sort)\n" + "dm uclass [name] Dump list of instances for each uclass" ; #endif @@ -102,5 +116,5 @@ U_BOOT_CMD_WITH_SUBCMDS(dm, "Driver model low level access", dm_help_text, U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_dm_dump_drivers), DM_MEM U_BOOT_SUBCMD_MKENT(static, 1, 1, do_dm_dump_static_driver_info), - U_BOOT_SUBCMD_MKENT(tree, 2, 1, do_dm_dump_tree), - U_BOOT_SUBCMD_MKENT(uclass, 1, 1, do_dm_dump_uclass)); + U_BOOT_SUBCMD_MKENT(tree, 3, 1, do_dm_dump_tree), + U_BOOT_SUBCMD_MKENT(uclass, 2, 1, do_dm_dump_uclass)); diff --git a/drivers/core/dump.c b/drivers/core/dump.c index 3e77832a3a00..855d6ca002b7 100644 --- a/drivers/core/dump.c +++ b/drivers/core/dump.c @@ -85,11 +85,35 @@ static void show_devices(struct udevice *dev, int depth, int last_flag, } } -void dm_dump_tree(bool sort) +void dm_dump_tree(char *uclass, bool sort) { struct udevice *root; - root = dm_root(); + if (uclass) { + char *device; + enum uclass_id id; + + device = strchr(uclass, ':'); + if (!device) { + printf("name %s: invalid format\n", uclass); + return; + } + *device = '\0'; + device++; + + id = uclass_get_by_name(uclass); + if (id == UCLASS_INVALID) { + printf("uclass %s: not found\n", uclass); + return; + } + if (uclass_find_device_by_name(id, device, &root)) { + printf("device %s:%s: not found\n", uclass, device); + return; + } + } else { + root = dm_root(); + } + if (root) { int dev_cou
Re: [PATCH] cmd: dm: allow for selecting uclass and device
Hi Simon, On Mon, Aug 21, 2023 at 09:22:54PM -0600, Simon Glass wrote: > Hi AKASHI, > > On Mon, 21 Aug 2023 at 20:46, AKASHI Takahiro > wrote: > > > > The output from "dm tree" or "dm uclass" is a bit annoying > > if the number of devices available on the system is huge. > > (This is especially true on sandbox when I debug some DM code.) > > > > With this patch, we can specify the uclass or the device > > that we are interested in in order to limit the output. > > > > For instance, > > > > => dm uclass usb > > uclass 121: usb > > 0 usb@1 @ 0bd008b0, seq 1 > > > > => dm tree usb:usb@1 > > Perhaps this should just provide a substring to search for and it can > find everything with a uclass name or device name that contains the > string? Well, I wanted to implement the feature with minimum effort, using the existing API, like uclass_find_device_by_name(). Well, I'll try. > Otherwise, can you drop the usb. part ? Is it needed? > > > Class Index Probed DriverName > > --- > > usb 0 [ ] usb_sandbox usb@1 > > usb_hub 0 [ ] usb_hub `-- hub > > usb_emul 0 [ ] usb_sandbox_hub `-- hub-emul > > usb_emul 1 [ ] usb_sandbox_flash |-- flash-stick@0 > > usb_emul 2 [ ] usb_sandbox_flash |-- flash-stick@1 > > usb_emul 3 [ ] usb_sandbox_flash |-- flash-stick@2 > > usb_emul 4 [ ] usb_sandbox_keyb `-- keyb@3 > > > > Please note that, at "dm tree", the uclass name (usb) as well as > > the device name (usb@1) is required. > > > > Signed-off-by: AKASHI Takahiro > > --- > > cmd/dm.c| 30 > > drivers/core/dump.c | 48 +++-- > > include/dm/util.h | 13 > > 3 files changed, 73 insertions(+), 18 deletions(-) > > Thanks, I've been wanting this for ages. Me, too :) > Can you please add doc/ as well? Yes. > > > > diff --git a/cmd/dm.c b/cmd/dm.c > > index 3263547cbec6..99268df2f87a 100644 > > --- a/cmd/dm.c > > +++ b/cmd/dm.c > > @@ -59,11 +59,20 @@ static int do_dm_dump_static_driver_info(struct cmd_tbl > > *cmdtp, int flag, > > static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, > >char *const argv[]) > > { > > - bool sort; > > + bool sort = false; > > + char *device = NULL; > > > > - sort = argc > 1 && !strcmp(argv[1], "-s"); > > + if (argc > 1) { > > + if (!strcmp(argv[1], "-s")) { > > + sort = true; > > + argc--; > > + argv++; > > + } > > + if (argc > 1) > > + device = argv[1]; > > + } > > > > - dm_dump_tree(sort); > > + dm_dump_tree(device, sort); > > > > return 0; > > } > > @@ -71,7 +80,12 @@ static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int > > flag, int argc, > > static int do_dm_dump_uclass(struct cmd_tbl *cmdtp, int flag, int argc, > > char *const argv[]) > > { > > - dm_dump_uclass(); > > + char *uclass = NULL; > > + > > + if (argc > 1) > > + uclass = argv[1]; > > + > > + dm_dump_uclass(uclass); > > > > return 0; > > } > > @@ -91,8 +105,8 @@ static char dm_help_text[] = > > "dm drivers Dump list of drivers with uclass and instances\n" > > DM_MEM_HELP > > "dm staticDump list of drivers with static platform data\n" > > - "dm tree [-s] Dump tree of driver model devices (-s=sort)\n" > > - "dm uclassDump list of instances for each uclass" > > + "dm tree [-s][name] Dump tree of driver model devices (-s=sort)\n" > > + "dm uclass [name] Dump list of instances for each uclass" > > ; > > #endif > > > > @@ -102,5 +116,5 @@ U_BOOT_CMD_WITH_SUBCMDS(dm, "Driver model low level > > access", dm_help_text, > > U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_dm_dump_drivers), > > DM_MEM > > U_BOOT_SUBCMD_MKENT(static,
[PATCH v2] cmd: dm: allow for selecting uclass and device
The output from "dm tree" or "dm uclass" is a bit annoying if the number of devices available on the system is huge. (This is especially true on sandbox when I debug some DM code.) With this patch, we can specify the uclass name or the device name that we are interested in in order to limit the output. For instance, => dm uclass usb uclass 121: usb 0 usb@1 @ 0bcff8b0, seq 1 uclass 124: usb => dm tree usb:usb@1 Class Index Probed DriverName --- usb 0 [ ] usb_sandbox usb@1 usb_hub 0 [ ] usb_hub `-- hub usb_emul 0 [ ] usb_sandbox_hub `-- hub-emul usb_emul 1 [ ] usb_sandbox_flash |-- flash-stick@0 usb_emul 2 [ ] usb_sandbox_flash |-- flash-stick@1 usb_emul 3 [ ] usb_sandbox_flash |-- flash-stick@2 usb_emul 4 [ ] usb_sandbox_keyb `-- keyb@3 If you want forward-matching against a uclass or udevice name, you can specify "-e" option. => dm uclass -e usb uclass 15: usb_emul 0 hub-emul @ 0bcffb00, seq 0 1 flash-stick@0 @ 0bcffc30, seq 1 2 flash-stick@1 @ 0bcffdc0, seq 2 3 flash-stick@2 @ 0bcfff50, seq 3 4 keyb@3 @ 0bd000e0, seq 4 uclass 64: usb_mass_storage uclass 121: usb 0 usb@1 @ 0bcff8b0, seq 1 uclass 122: usb_dev_generic uclass 123: usb_hub 0 hub @ 0bcff9b0, seq 0 uclass 124: usb => dm tree -e usb Class Index Probed DriverName --- usb 0 [ ] usb_sandbox usb@1 usb_hub 0 [ ] usb_hub `-- hub usb_emul 0 [ ] usb_sandbox_hub `-- hub-emul usb_emul 1 [ ] usb_sandbox_flash |-- flash-stick@0 usb_emul 2 [ ] usb_sandbox_flash |-- flash-stick@1 usb_emul 3 [ ] usb_sandbox_flash |-- flash-stick@2 usb_emul 4 [ ] usb_sandbox_keyb `-- keyb@3 Signed-off-by: AKASHI Takahiro --- v2 - allow for forward-matching against the name - update command doc --- cmd/dm.c | 48 ++ doc/usage/cmd/dm.rst | 30 ++- drivers/core/dump.c | 116 --- include/dm/util.h| 15 -- 4 files changed, 165 insertions(+), 44 deletions(-) diff --git a/cmd/dm.c b/cmd/dm.c index 3263547cbec6..1aa86aab9c1c 100644 --- a/cmd/dm.c +++ b/cmd/dm.c @@ -59,11 +59,26 @@ static int do_dm_dump_static_driver_info(struct cmd_tbl *cmdtp, int flag, static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - bool sort; - - sort = argc > 1 && !strcmp(argv[1], "-s"); - - dm_dump_tree(sort); + bool extended = false, sort = false; + char *device = NULL; + + for (; argc > 1; argc--, argv++) { + if (argv[1][0] != '-') + break; + + if (!strcmp(argv[1], "-e")) { + extended = true; + } else if (!strcmp(argv[1], "-s")) { + sort = true; + } else { + printf("Unknown parameter: %s\n", argv[1]); + return 0; + } + } + if (argc > 1) + device = argv[1]; + + dm_dump_tree(device, extended, sort); return 0; } @@ -71,7 +86,20 @@ static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, static int do_dm_dump_uclass(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - dm_dump_uclass(); + bool extended = false; + char *uclass = NULL; + + if (argc > 1) { + if (!strcmp(argv[1], "-e")) { + extended = true; + argc--; + argv++; + } + if (argc > 1) + uclass = argv[1]; + } + + dm_dump_uclass(uclass, extended); return 0; } @@ -91,8 +119,8 @@ static char dm_help_text[] = "dm drivers Dump list of drivers with uclass and instances\n" DM_MEM_HELP "dm staticDump list of drivers with static platform data\n" - "dm tree [-s] Dump tree of driver model devices (-s=sort)\n" - "dm uclassDump list of instances for each uclass" + "dm tree [-s][-e][name] Dump tree of driver model devices (-s=sort)\n" + "dm uclass [-e][name] Dump list of instances for each uclass" ; #endif @@ -102,5 +130,5 @@ U_BOOT_CMD_WITH_SUBCMDS(dm, "Driver model low level access", dm_help_text, U_BOO
Re: [PATCH 1/2] cmd: efidebug: add uri device path
Hi Kojima-san, On Wed, Aug 23, 2023 at 05:37:19PM +0900, Masahisa Kojima wrote: > This adds the URI device path option for 'boot add' subcommand. > User can add the URI load option for downloading ISO image file > or EFI application through network(e.g. HTTP). > > Signed-off-by: Masahisa Kojima > --- > cmd/efidebug.c | 39 +++ > 1 file changed, 39 insertions(+) > > diff --git a/cmd/efidebug.c b/cmd/efidebug.c > index 0be3af3e76..62f867df2a 100644 > --- a/cmd/efidebug.c > +++ b/cmd/efidebug.c > @@ -829,6 +829,44 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int > flag, > argc -= 1; > argv += 1; > break; > + case 'u': > + { > + char *pos; > + int uridp_len; > + struct efi_device_path_uri *uridp; > + > + if (argc < 3 || lo.label) { > + r = CMD_RET_USAGE; > + goto out; > + } > + id = (int)hextoul(argv[1], &endp); > + if (*endp != '\0' || id > 0x) > + return CMD_RET_USAGE; > + > + efi_create_indexed_name(var_name16, sizeof(var_name16), > + "Boot", id); > + > + label = efi_convert_string(argv[2]); > + if (!label) > + return CMD_RET_FAILURE; > + lo.label = label; > + > + uridp_len = sizeof(struct efi_device_path) + > strlen(argv[3]) + 1; > + fp_free = efi_alloc(uridp_len + sizeof(END)); > + uridp = (struct efi_device_path_uri *)fp_free; > + uridp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE; > + uridp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_URI; > + uridp->dp.length = uridp_len; > + strcpy(uridp->uri, argv[3]); > + pos = (char *)uridp + uridp_len; > + memcpy(pos, &END, sizeof(END)); > + fp_size += uridp_len + sizeof(END); > + file_path = (struct efi_device_path *)uridp; > + argc -= 3; > + argv += 3; > + break; > + } > + > default: > r = CMD_RET_USAGE; > goto out; > @@ -1492,6 +1530,7 @@ static char efidebug_help_text[] = > " -b|-B[:] \n" > " -i|-I [:] \n" > " (-b, -i for short form device path)\n" > + " -u \n" It might be a matter of personal preference, but since the current syntax of efidebug is already much complex, I don't want to add more options unless it's necessary. How about re-using "-B" option, say => efidebug -B 3 debian-netinst uri - https://foo.com/baa BTW, I think that and should have been moved out of "-b|B" when Ilias introduced this new syntax. -Takahiro Akashi > " -s ''\n" > "efidebug boot rm [ [ [...]]]\n" > " - delete UEFI Boot variables\n" > -- > 2.34.1 >
Re: [PATCH 2/2] efi_loader: support boot from URI device path
Kojima-san, On Wed, Aug 23, 2023 at 05:37:20PM +0900, Masahisa Kojima wrote: > This supports to boot from the URI device path. > When user selects the URI device path, bootmgr downloads > the file using wget into the address specified by loadaddr > env variable. > If the file is .iso or .img file, mount the image with blkmap > then try to boot with the default file(e.g. EFI/BOOT/BOOTAA64.EFI). > If the file is .efi file, load and start the downloaded file. Is this behavior part of UEFI specification? Even so, it would be better to describe it in uefi.rst (or else), including URI usage. > Signed-off-by: Masahisa Kojima > --- > lib/efi_loader/efi_bootmgr.c | 213 +++ > 1 file changed, 213 insertions(+) > > diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c > index a40762c74c..8b20f486f2 100644 > --- a/lib/efi_loader/efi_bootmgr.c > +++ b/lib/efi_loader/efi_bootmgr.c > @@ -7,10 +7,14 @@ > > #define LOG_CATEGORY LOGC_EFI > > +#include > +#include > #include > #include > +#include > #include > #include > +#include > #include > #include > #include > @@ -168,6 +172,209 @@ out: > return ret; > } > > +#if (IS_ENABLED(CONFIG_BLKMAP) && IS_ENABLED(CONFIG_CMD_WGET) && > IS_ENABLED(CONFIG_CMD_DNS)) > +/** > + * mount_image() - mount the image > + * > + * @lo_label label of load option > + * @file_sizefile size > + * @handle: pointer to handle for newly installed image > + * Return: status code > + */ > +static efi_status_t mount_image(u16 *lo_label, int file_size, > + efi_handle_t *handle) I wonder why not adding "address" parameter to make this function more generic as Simon suggested. > +{ > + int err; > + efi_status_t ret; > + char *label = NULL, *p; > + lbaint_t blknum; > + struct udevice *bm_dev; > + efi_handle_t bm_handle; > + struct udevice *blk, *partition; > + struct efi_handler *handler; > + struct efi_device_path *file_path; > + struct efi_device_path *device_path; > + > + label = efi_alloc(utf16_utf8_strlen(lo_label) + 1); > + if (!label) > + return EFI_OUT_OF_RESOURCES; > + > + p = label; > + utf16_utf8_strcpy(&p, lo_label); > + err = blkmap_create(label, NULL); > + if (err) { > + log_err("failed to create blkmap\n"); > + ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + bm_dev = blkmap_from_label(label); > + if (!bm_dev) { > + log_err("\"%s\" is not the name of any known blkmap\n", label); > + ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + > + blknum = file_size / 512; /* TODO: don't use literal value. */ > + err = blkmap_map_pmem(bm_dev, 0, blknum, image_load_addr); > + if (err) { > + log_err("Unable to map %#llx at block %d : %d\n", > + (unsigned long long)image_load_addr, 0, err); > + ret = EFI_INVALID_PARAMETER; > + goto out; > + } > + log_info("Block %d+0x" LBAF " mapped to %#llx\n", 0, blknum, > + (unsigned long long)image_load_addr); > + > + /* TODO: without calling this, partition devices are not binded. */ > + blk_list_part(UCLASS_BLKMAP); I think that blkmap should provide a way to *probe* its child block device. In fact, struct blkmap *bm = dev_get_plat(bm_dev); device_probe(bm->blk); should work. (Not tested though) > + > + /* > + * Search the partition having EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, > + * then try to load with the default boot file(e.g. > EFI/BOOT/BOOTAA64.EFI). > + */ > + device_foreach_child(blk, bm_dev) Does bm_dev have more than one block devices? > + { > + device_foreach_child(partition, blk) > + { > + if (dev_tag_get_ptr(partition, DM_TAG_EFI, > + (void **)&bm_handle)) { > + log_warning("DM_TAG_EFI not found\n"); > + continue; > + } > + > + ret = efi_search_protocol( > + bm_handle, > + &efi_simple_file_system_protocol_guid, > + &handler); > + if (ret != EFI_SUCCESS) > + continue; > + > + ret = efi_search_protocol( > + bm_handle, &efi_guid_device_path, &handler); > + if (ret != EFI_SUCCESS) > + continue; > + > + ret = efi_protocol_open(handler, (void **)&device_path, > + efi_root, NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL); > + if (ret != EFI_SUCCESS) > + continue; > + > +
Re: [PATCH 2/2] efi_loader: support boot from URI device path
On Thu, Aug 24, 2023 at 11:24:31AM +0900, AKASHI Takahiro wrote: > Kojima-san, > > On Wed, Aug 23, 2023 at 05:37:20PM +0900, Masahisa Kojima wrote: > > This supports to boot from the URI device path. > > When user selects the URI device path, bootmgr downloads > > the file using wget into the address specified by loadaddr > > env variable. > > If the file is .iso or .img file, mount the image with blkmap > > then try to boot with the default file(e.g. EFI/BOOT/BOOTAA64.EFI). > > If the file is .efi file, load and start the downloaded file. > > Is this behavior part of UEFI specification? > Even so, it would be better to describe it in uefi.rst (or else), > including URI usage. > > > Signed-off-by: Masahisa Kojima > > --- > > lib/efi_loader/efi_bootmgr.c | 213 +++ > > 1 file changed, 213 insertions(+) > > > > diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c > > index a40762c74c..8b20f486f2 100644 > > --- a/lib/efi_loader/efi_bootmgr.c > > +++ b/lib/efi_loader/efi_bootmgr.c > > @@ -7,10 +7,14 @@ > > > > #define LOG_CATEGORY LOGC_EFI > > > > +#include > > +#include > > #include > > #include > > +#include > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -168,6 +172,209 @@ out: > > return ret; > > } > > > > +#if (IS_ENABLED(CONFIG_BLKMAP) && IS_ENABLED(CONFIG_CMD_WGET) && > > IS_ENABLED(CONFIG_CMD_DNS)) > > +/** > > + * mount_image() - mount the image > > + * > > + * @lo_label label of load option > > + * @file_size file size > > + * @handle:pointer to handle for newly installed image > > + * Return: status code > > + */ > > +static efi_status_t mount_image(u16 *lo_label, int file_size, > > + efi_handle_t *handle) > > I wonder why not adding "address" parameter to make this function > more generic as Simon suggested. > > > +{ > > + int err; > > + efi_status_t ret; > > + char *label = NULL, *p; > > + lbaint_t blknum; > > + struct udevice *bm_dev; > > + efi_handle_t bm_handle; > > + struct udevice *blk, *partition; > > + struct efi_handler *handler; > > + struct efi_device_path *file_path; > > + struct efi_device_path *device_path; > > + > > + label = efi_alloc(utf16_utf8_strlen(lo_label) + 1); > > + if (!label) > > + return EFI_OUT_OF_RESOURCES; > > + > > + p = label; > > + utf16_utf8_strcpy(&p, lo_label); > > + err = blkmap_create(label, NULL); > > + if (err) { > > + log_err("failed to create blkmap\n"); > > + ret = EFI_INVALID_PARAMETER; > > + goto out; > > + } > > + bm_dev = blkmap_from_label(label); > > + if (!bm_dev) { > > + log_err("\"%s\" is not the name of any known blkmap\n", label); > > + ret = EFI_INVALID_PARAMETER; > > + goto out; > > + } > > + > > + blknum = file_size / 512; /* TODO: don't use literal value. */ > > + err = blkmap_map_pmem(bm_dev, 0, blknum, image_load_addr); > > + if (err) { > > + log_err("Unable to map %#llx at block %d : %d\n", > > + (unsigned long long)image_load_addr, 0, err); > > + ret = EFI_INVALID_PARAMETER; > > + goto out; > > + } > > + log_info("Block %d+0x" LBAF " mapped to %#llx\n", 0, blknum, > > +(unsigned long long)image_load_addr); > > + > > + /* TODO: without calling this, partition devices are not binded. */ > > + blk_list_part(UCLASS_BLKMAP); > > I think that blkmap should provide a way to *probe* its child block > device. In fact, > struct blkmap *bm = dev_get_plat(bm_dev); > device_probe(bm->blk); > should work. (Not tested though) > > > + > > + /* > > +* Search the partition having EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, > > +* then try to load with the default boot file(e.g. > > EFI/BOOT/BOOTAA64.EFI). > > +*/ > > + device_foreach_child(blk, bm_dev) > > Does bm_dev have more than one block devices? > > > + { > > + device_foreach_child(partition, blk) > > + { > > + if (dev_tag_get_ptr(partition, DM_TAG_EFI, > > +
[RFC] make sandbox UT more generic
Hi, I'm working on implementing SCMI-based pinctrl/gpio driver, and want to re-use sandbox UT to test the code. However, It is somehow sandbox-specific (with additional DT nodes). How can/should we make it more generic for other targets/drivers rather than just by copying the test code? (I have already created a test for pinmux since there is only one existing scenario, but gpio test has many.) Even if I say 'generic', my case may be special since real hardware (device drivers) cannot always run all the test cases, while SCMI-based drivers potentially can with a dummy SCMI server for sandbox. See: drivers/firmware/scmi/sandbox-scmi_agent.c Thanks, -Takahiro Akashi
Re: [PATCH v2] cmd: dm: allow for selecting uclass and device
On Wed, Aug 30, 2023 at 09:48:48PM -0600, Simon Glass wrote: > Hi AKASHI, > > On Tue, 22 Aug 2023 at 19:50, AKASHI Takahiro > wrote: > > > > The output from "dm tree" or "dm uclass" is a bit annoying > > if the number of devices available on the system is huge. > > (This is especially true on sandbox when I debug some DM code.) > > > > With this patch, we can specify the uclass name or the device > > name that we are interested in in order to limit the output. > > > > For instance, > > > > => dm uclass usb > > uclass 121: usb > > 0 usb@1 @ 0bcff8b0, seq 1 > > > > uclass 124: usb > > > > => dm tree usb:usb@1 > > Class Index Probed DriverName > > --- > > usb 0 [ ] usb_sandbox usb@1 > > usb_hub 0 [ ] usb_hub `-- hub > > usb_emul 0 [ ] usb_sandbox_hub `-- hub-emul > > usb_emul 1 [ ] usb_sandbox_flash |-- flash-stick@0 > > usb_emul 2 [ ] usb_sandbox_flash |-- flash-stick@1 > > usb_emul 3 [ ] usb_sandbox_flash |-- flash-stick@2 > > usb_emul 4 [ ] usb_sandbox_keyb `-- keyb@3 > > > > If you want forward-matching against a uclass or udevice name, > > you can specify "-e" option. > > I don't really know what 'forward matching' means. Really? I believed that forward-matching was a common word. I meant that it searches for any string starting with a specific sub-string. In other words, it would be "^" in a regular expression. So, for example, "usb" should match with "usbABC", "usb-DEF", "usb_GHI" and so on, but not match with "ABCusb". > Please use forward instead of forword in the code > > > > > => dm uclass -e usb > > uclass 15: usb_emul > > 0 hub-emul @ 0bcffb00, seq 0 > > 1 flash-stick@0 @ 0bcffc30, seq 1 > > 2 flash-stick@1 @ 0bcffdc0, seq 2 > > 3 flash-stick@2 @ 0bcfff50, seq 3 > > 4 keyb@3 @ 0bd000e0, seq 4 > > > > uclass 64: usb_mass_storage > > > > uclass 121: usb > > 0 usb@1 @ 0bcff8b0, seq 1 > > > > uclass 122: usb_dev_generic > > > > uclass 123: usb_hub > > 0 hub @ 0bcff9b0, seq 0 > > > > uclass 124: usb > > > > => dm tree -e usb > > Class Index Probed DriverName > > --- > > usb 0 [ ] usb_sandbox usb@1 > > usb_hub 0 [ ] usb_hub `-- hub > > usb_emul 0 [ ] usb_sandbox_hub `-- hub-emul > > usb_emul 1 [ ] usb_sandbox_flash |-- flash-stick@0 > > usb_emul 2 [ ] usb_sandbox_flash |-- flash-stick@1 > > usb_emul 3 [ ] usb_sandbox_flash |-- flash-stick@2 > > usb_emul 4 [ ] usb_sandbox_keyb `-- keyb@3 > > > > Signed-off-by: AKASHI Takahiro > > --- > > v2 > > - allow for forward-matching against the name > > - update command doc > > --- > > cmd/dm.c | 48 ++ > > doc/usage/cmd/dm.rst | 30 ++- > > drivers/core/dump.c | 116 --- > > include/dm/util.h| 15 -- > > 4 files changed, 165 insertions(+), 44 deletions(-) > > Reviewed-by: Simon Glass > > Thanks for doing this. It will be a big time-saver. I also wonder if > it would be better if the default were to do a substring search and Initially, I implemented so, but felt it is annoying to see (sometimes many) unexpected matched devices, especially when you know the exact name of device. See my example "dm uclass -e usb". > you have to add a flag to search for a single device? Does 'single' mean the first matched word or exactly-same one? Either way, I don't have a strong opinion here, though. Thanks, -Takahiro Akashi > > See below > > > > > diff --git a/cmd/dm.c b/cmd/dm.c > > index 3263547cbec6..1aa86aab9c1c 100644 > > --- a/cmd/dm.c > > +++ b/cmd/dm.c > > @@ -59,11 +59,26 @@ static int do_dm_dump_static_driver_info(struct cmd_tbl > > *cmdtp, int flag, > > static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, > >char *const argv[]) > > { > > - bool sort; > > - > > - sort = argc > 1 &&a
Re: [RFC] make sandbox UT more generic
Hi Simon, On Wed, Aug 30, 2023 at 08:49:05PM -0600, Simon Glass wrote: > Hi, > > On Wed, 30 Aug 2023 at 18:38, AKASHI Takahiro > wrote: > > > > Hi, > > > > I'm working on implementing SCMI-based pinctrl/gpio driver, > > and want to re-use sandbox UT to test the code. However, > > It is somehow sandbox-specific (with additional DT nodes). > > How can/should we make it more generic for other targets/drivers > > rather than just by copying the test code? > > (I have already created a test for pinmux since there is only > > one existing scenario, but gpio test has many.) > > > > Even if I say 'generic', my case may be special since real > > hardware (device drivers) cannot always run all the test cases, > > while SCMI-based drivers potentially can with a dummy SCMI server > > for sandbox. > > See: > > drivers/firmware/scmi/sandbox-scmi_agent.c > > We don't have a good way to test drivers that talk to hardware, in general. > > For I2C, SPI and some PCI devices you can sometimes write an emulator > for the chip and then your driver can talk to the emulator as if it > were talking to the hardware. Sandbox does actually support that with > memory-mapped I/O too, although it is fairly rarely used. Well, I don't want or need to emulate some *real* hardware. Instead, I would like to emulate what the current sandbox drivers (pinctrl-sandbox.c and gpio/sandbox.c) emulate so that we can re-use (some portion of) test cases for sandbox (test/dm/pinmux.c and gpio.c). As you might know, SCMI protocol with associated drivers on U-Boot is so generic that it would be able to talk to any of real pinctrl/gpio drivers/firmware (say, run on OPTEE or SCP). By implementing/mimicking protocol messages in sandbox-scmi_agent.c, SCMI drivers are expected to provide *virtual* pinctrl/gpio devices similar to what sandbox does. I have already implemented pinmux test with some tweaks by copying test/dm/pinmux.c and duplicating almost the same DT nodes as "pinctrl-gpio" in test.dts. But I'm looking for any other means without test code duplication. Did I clarify my question a bit? -Takahiro Akashi > We have done this a lot with Zephyr, as well[1] and achieved 90% code > coverage on some boards. > > But I'm not quite sure I am answering the right question, so I will stop here. > > Regards, > Simon > > [1] https://www.youtube.com/watch?v=usXCAXR2G_c
[RFC 0/6] firmware: scmi: add SCMI pinctrl protocol support
This is an RFC and meant to get feedback from other developers as - the specification (pinctrl part) is still in a draft - the upstream patch for linux, including dt bindings, is still WIP - I'm not confident the drivers are generic enough to cover most HWs - The tests ("ut") doesn't cover all the features yet This patch series allows users to access SCMI pin control protocol provided by SCMI server (platform). See SCMI specification document v3.2 beta 2[1] for more details about SCMI pin control protocol. The implementation consists of two layers: - basic helper functions for SCMI pin control protocol in drivers/firmware/scmi/pinctrl.c (patch#2) - DM-compliant pinctrl/gpio drivers, which utilizes the helper functions, in drivers/pinctrl/pinctrl-scmi.c (patch#3,#4) [1] https://developer.arm.com/documentation/den0056/e/?lang=en DT bindings === Upstream pinctrl patch for linux defines the bindings in [2] though it doesn't say much. I expect that my implementation basically complies with U-Boot's generic bindings described in [3], but not all the features are verified. As for gpio, unless you hard-code pin assignments directly in a device driver, my implementation allows the following alternatives in DT. Either way, we may need an additional binding description for gpio. (A) scmi { ... // other protocols scmi_pinctrl: protocol@19 { // Pin control protocol ... {pinmux definitions}... // if any, including GPIO? } } scmi_gpio: scmi_gpio { compatible = "arm,scmi-gpio-generic"; gpio-controller; #gpio-cells = <2>; gpio-ranges = <&scmi_pinctrl 0 5 4>, <&scmi_pinctrl 4 0 0>; gpio-ranges-group-names = "", "ANOTHER_GPIO_GROUP"; } some_device { ... reset-gpios = <&scmi_gpio 0 GPIO_ACTIVE_HIGH>; } (B) scmi { ... // other protocols scmi_pinctrl: protocol@19 { // Pin control protocol ... {pinmux definitions}... // if any, including GPIO? scmi_gpio: scmi_gpio { // no need for "compatible" gpio-controller; #gpio-cells = <2>; gpio-ranges = <&scmi_pinctrl 0 5 4>, <&scmi_pinctrl 4 0 0>; gpio-ranges-group-names = "", "ANOTHER_GPIO_GROUP"; } } } some_device { ... reset-gpios = <&scmi_gpio 0 GPIO_ACTIVE_HIGH>; } (C) if "gpio-ranges" is missing in gpio definition, assume 1:1 mapping, i.e. use a native pinctrl pin number (5). some_device { ... reset-gpios = <&scmi_gpio 5 GPIO_ACTIVE_HIGH>; } [2] https://lkml.iu.edu/hypermail/linux/kernel/2308.1/01084.html [3] /doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt /doc/device-tree-bindings/gpio/gpio.txt Test The patch series was tested on the following platforms: * sandbox ("ut dm pinmux" and manually using gpio command) Prerequisite: = * This patch series is based on my WIP "Base protocol support" patches on v2023.10-rc3. You can fetch the whole code from [4]. [4] https://git.linaro.org/people/takahiro.akashi/u-boot.git branch:scmi/pinctrl Patches: Patch#1: Add SCMI base protocol driver Patch#2-#4: Add drivers Patch#5-#6: Test related Change history: === RFC (Sep 6, 2023) * initial release as RFC AKASHI Takahiro (6): firmware: scmi: fix protocol enumeration logic firmware: scmi: add pinctrl protocol support pinctrl: add scmi driver gpio: add scmi driver based on pinctrl firmware: scmi: add pseudo pinctrl protocol support on sandbox test: dm: add SCMI pinctrl test arch/sandbox/dts/test.dts | 115 +++ cmd/scmi.c |1 + drivers/firmware/scmi/Kconfig |3 + drivers/firmware/scmi/Makefile |1 + drivers/firmware/scmi/pinctrl.c| 412 drivers/firmware/scmi/sandbox-scmi_agent.c | 722 + drivers/firmware/scmi/scmi_agent-uclass.c | 18 +- drivers/pinctrl/Kconfig| 11 + drivers/pinctrl/Makefile |1 + drivers/pinctrl/pinctrl-scmi.c | 1071 include/scmi_agent-uclass.h|2 + include/scmi_protocols.h | 435 test/dm/scmi.c | 62 ++ 13 files changed, 2852 insertions(+), 2 deletions(-) create mode 100644 drivers/firmware/scmi/pinctrl.c create mode 100644 drivers/pinctrl/pinctrl-scmi.c -- 2.34.1
[RFC 1/6] firmware: scmi: fix protocol enumeration logic
The original logic in enumerating all the protocols accidentally modifies a *loop* variable, node, at Voltage domain protocol. So subsequent protocol nodes in a device tree won't be detected. Signed-off-by: AKASHI Takahiro --- drivers/firmware/scmi/scmi_agent-uclass.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 46a2933d51a4..79584c00a066 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -422,8 +422,11 @@ static int scmi_bind_protocols(struct udevice *dev) case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) && scmi_protocol_is_supported(dev, protocol_id)) { - node = ofnode_find_subnode(node, "regulators"); - if (!ofnode_valid(node)) { + ofnode sub_node; + + sub_node = ofnode_find_subnode(node, + "regulators"); + if (!ofnode_valid(sub_node)) { dev_err(dev, "no regulators node\n"); return -ENXIO; } -- 2.34.1
[RFC 2/6] firmware: scmi: add pinctrl protocol support
With this patch, transport-level utility functions for SCMI pinctrl protocol are added. DM-compliant device drivers, pinctrl and gpio, are added in the following patches. Signed-off-by: AKASHI Takahiro --- cmd/scmi.c| 1 + drivers/firmware/scmi/Kconfig | 3 + drivers/firmware/scmi/Makefile| 1 + drivers/firmware/scmi/pinctrl.c | 412 drivers/firmware/scmi/scmi_agent-uclass.c | 11 + include/scmi_agent-uclass.h | 2 + include/scmi_protocols.h | 435 ++ 7 files changed, 865 insertions(+) create mode 100644 drivers/firmware/scmi/pinctrl.c diff --git a/cmd/scmi.c b/cmd/scmi.c index 5efec8ad87fd..ae7892381e0a 100644 --- a/cmd/scmi.c +++ b/cmd/scmi.c @@ -33,6 +33,7 @@ struct { {SCMI_PROTOCOL_ID_SENSOR, "Sensor management"}, {SCMI_PROTOCOL_ID_RESET_DOMAIN, "Reset domain management"}, {SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, "Voltage domain management"}, + {SCMI_PROTOCOL_ID_PIN_CONTROL, "Pin control"}, }; /** diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index 8cf85f0d7a12..e0cb7b70dede 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -41,3 +41,6 @@ config SCMI_AGENT_OPTEE help Enable the SCMI communication channel based on OP-TEE transport for compatible "linaro,scmi-optee". + +config SCMI_PINCTRL + bool diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index 1a23d4981709..bf6381332e9e 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -4,4 +4,5 @@ obj-y += smt.o obj-$(CONFIG_SCMI_AGENT_SMCCC) += smccc_agent.o obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SCMI_AGENT_OPTEE) += optee_agent.o +obj-$(CONFIG_SCMI_PINCTRL) += pinctrl.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o diff --git a/drivers/firmware/scmi/pinctrl.c b/drivers/firmware/scmi/pinctrl.c new file mode 100644 index ..88ec57dc3d53 --- /dev/null +++ b/drivers/firmware/scmi/pinctrl.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SCMI Pin control protocol as U-Boot device + * + * Copyright (C) 2023 Linaro Limited + * author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct scmi_pinctrl_priv - Private data for SCMI Pin control protocol + * @channel: Reference to the SCMI channel to use + */ +struct scmi_pinctrl_priv { + struct scmi_channel *channel; +}; + +int scmi_pinctrl_protocol_attrs(struct udevice *dev, u32 *num_pins, + u32 *num_groups, u32 *num_functions) +{ + struct scmi_pinctrl_protocol_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PROTOCOL_ATTRIBUTES, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !num_pins || !num_groups || !num_functions) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *num_groups = SCMI_PINCTRL_ATTRS_NUM_GROUPS(out.attributes_low); + *num_pins = SCMI_PINCTRL_ATTRS_NUM_PINS(out.attributes_low); + *num_functions = SCMI_PINCTRL_ATTRS_NUM_FUNCTIONS(out.attributes_high); + + return 0; +} + +int scmi_pinctrl_attrs(struct udevice *dev, u32 id, u32 flags, + bool *extended_name, u8 **name) +{ + struct scmi_pinctrl_attrs_in in; + struct scmi_pinctrl_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_ATTRIBUTES, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !extended_name || !name) + return -EINVAL; + + in.id = id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *extended_name = SCMI_PINCTRL_ATTRS_EXTENDED_NAME(out.attributes); + *name = strdup(out.name); + if (!*name) + return -ENOMEM; + + return 0; +} + +int scmi_pinctrl_list_assocs(struct udevice *dev, u32 id, u32 flags, +u16 **array) +{ + struct scmi_pinctrl_list_assocs_in in; + struct scmi_pinctrl_list_assocs
[RFC 3/6] pinctrl: add scmi driver
This DM-compliant driver deals with SCMI pinctrl protocol and presents pinctrl devices exposed by SCMI firmware (server). Signed-off-by: AKASHI Takahiro --- drivers/pinctrl/Kconfig| 11 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-scmi.c | 537 + 3 files changed, 549 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-scmi.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 75b3ff47a2e8..d02f5db550c8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -256,6 +256,17 @@ config PINCTRL_SANDBOX Currently, this driver actually does nothing but print debug messages when pinctrl operations are invoked. +config PINCTRL_SCMI + bool "SCMI pinctrl driver" + depends on SCMI_FIRMWARE + select SCMI_PINCTRL + help + This enables pinctrl driver base on SCMI. + + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config PINCTRL_SINGLE bool "Single register pin-control and pin-multiplex driver" depends on DM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index fc1f01a02cbd..a791df022b7d 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_PINCTRL_MSCC)+= mscc/ obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_ARCH_NEXELL) += nexell/ obj-$(CONFIG_PINCTRL_QE) += pinctrl-qe-io.o +obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32)+= pinctrl_stm32.o diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c new file mode 100644 index ..3ebdad57b86c --- /dev/null +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -0,0 +1,537 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Linaro Limited + * Author: AKASHI Takahiro + */ + +#define LOG_CATEGORY UCLASS_PINCTRL + +#include +#include +#include +#include +#include +#include +#include + +/** + * struct scmi_pin - attributes for a pin + * @name: Name of pin + * @value: Value of pin + * @flags: A set of flags + * @function: Function selected + * @status:An array of status of configuration types + */ +struct scmi_pin { + char*name; + u32 value; + u32 flags; + unsigned intfunction; + u32 status[SCMI_PINCTRL_CONFIG_RESERVED]; +}; + +/** + * struct scmi_group - attributes for a group + * @name: Name of group + * @num_pins: A number of pins + * @pins: An array of pin id's + */ +struct scmi_group { + char*name; + unsigned intnum_pins; + u16 *pins; +}; + +/** + * struct scmi_pinctrl_priv - private data for pinctrl device + * @num_pins: A number of pins + * @num_groups:A number of groups + * @num_functions: A number of functions + * @pins: An array of pins + * @groups:An array of groups + * @functions: An array of function names + */ +struct scmi_pinctrl_priv { + unsigned intnum_pins; + unsigned intnum_groups; + unsigned intnum_functions; + struct scmi_pin *pins; + struct scmi_group *groups; + char**functions; +}; + +static const struct pinconf_param scmi_conf_params[] = { + { "default", SCMI_PINCTRL_CONFIG_DEFAULT, 1 }, + { "bias-bus-hold", SCMI_PINCTRL_CONFIG_BIAS_BUS_HOLD, 1 }, + { "bias-disable", SCMI_PINCTRL_CONFIG_BIAS_DISABLE, 1 }, + { "bias-high-impedance", SCMI_PINCTRL_CONFIG_BIAS_HI_IMPEDANCE, 1 }, + { "bias-pull-up", SCMI_PINCTRL_CONFIG_BIAS_PULL_UP, 1 }, + { "bias-pull-default", SCMI_PINCTRL_CONFIG_BIAS_PULL_DEF, 1 }, + { "bias-pull-down", SCMI_PINCTRL_CONFIG_BIAS_PULL_DOWN, 1 }, + { "drive-open-drain", SCMI_PINCTRL_CONFIG_DRIVE_OPEN_DRAIN, 1 }, + { "drive-open-source", SCMI_PINCTRL_CONFIG_DRIVE_OPEN_SOURCE, 1 }, + { "drive-push-pull", SCMI_PINCTRL_CONFIG_DRIVE_PUSH_PULL, 1 }, + { "drive-strength", SCMI_PINCTRL_CONFIG_DRIVE_STRENGTH, 0 }, + { "input-debounce", SCMI_PINCTRL_CONFIG_INPUT_DEBOUNCE, 0 }, + { "input-mode", SCMI_PINCTRL_CONFIG_INPUT_MODE, 1 }, + { "pull-mode", SCMI_PINCTRL_CONFIG_PULL_MODE, 0 }, + { "input-value", SCMI_PINCTRL_CONFIG_INPUT_VALUE, 0 }, + { "input-schmitt", SCMI_PINCTRL_CONFIG_INPUT_SCHMITT, 1 }, + { "low-power-mode", SCMI_PINCTRL_CONFIG_LOW_POWER_MODE, 1 }, + { "output-mode", SCMI_PINCTRL_CONFI
[RFC 4/6] gpio: add scmi driver based on pinctrl
This DM-compliant driver deals with SCMI pinctrl protocol and presents gpio devices exposed by SCMI firmware (server). Signed-off-by: AKASHI Takahiro --- drivers/pinctrl/pinctrl-scmi.c | 544 - 1 file changed, 539 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c index 3ebdad57b86c..73d385bdbfcc 100644 --- a/drivers/pinctrl/pinctrl-scmi.c +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -11,21 +11,20 @@ #include #include #include +#include #include +#include +#include #include /** * struct scmi_pin - attributes for a pin * @name: Name of pin - * @value: Value of pin - * @flags: A set of flags * @function: Function selected * @status:An array of status of configuration types */ struct scmi_pin { char*name; - u32 value; - u32 flags; unsigned intfunction; u32 status[SCMI_PINCTRL_CONFIG_RESERVED]; }; @@ -308,7 +307,6 @@ static int scmi_pinmux_group_set(struct udevice *dev, return 0; } -/* TODO: may be driver-specific */ /** * pinmux_property_set - Enable a pinmux group * @dev: SCMI pinctrl device to use @@ -424,6 +422,539 @@ const struct pinctrl_ops scmi_pinctrl_ops = { .set_state = pinctrl_generic_set_state, }; +#if CONFIG_IS_ENABLED(DM_GPIO) +/* + * GPIO part + */ + +/** + * struct scmi_pinctrl_gpio_plat - platform data + * @pinctrl_dev: Associated SCMI pinctrl device + * @gpio_map: A list of gpio mapping information + * @name: Name of ? + * @ngpios:A number of gpio pins + */ +struct scmi_pinctrl_gpio_plat { + struct list_head gpio_map; + char *name; + u32 ngpios; +}; + +/** + * struct scmi_pinctrl_gpio_map - gpio mapping information + * @gpio_pin: Start gpio pin selector + * @pinctrl_pin: Mapped start pinctrl pin selector, used for linear mapping + * @pinctrl_group: Name of an associated group, used for group namee mapping + * @num_pins: A number of pins + * @node: Node for a mapping list + */ +struct scmi_pinctrl_gpio_map { + struct udevice *pinctrl_dev; + u32 gpio_pin; + u32 pinctrl_pin; + u16 *pinctrl_group; + u32 num_pins; + struct list_head node; +}; + +/** + * map_to_id - Map a gpio pin offset to a pinctrl pin selector + * @dev: SCMI pinctrl device + * @offset:Pin offset + * @id:Pinctrl pin selector + * + * Map a gpio pin offset, @offset, to an associated pinctrl pin selector + * + * Return: 0 on success, -1 on failure + */ +static int map_to_id(struct udevice *dev, unsigned int offset, +struct udevice **pinctrl_dev, u32 *id) +{ + struct scmi_pinctrl_gpio_plat *plat = dev_get_plat(dev); + struct scmi_pinctrl_gpio_map *map; + + /* if no mapping is defined, return 1:1 pin */ + if (list_empty(&plat->gpio_map)) { + uclass_first_device(UCLASS_PINCTRL, pinctrl_dev); + if (!*pinctrl_dev) + return -1; + + *id = offset; + return 0; + } + + list_for_each_entry(map, &plat->gpio_map, node) { + if (offset >= map->gpio_pin && + offset < (map->gpio_pin + map->num_pins)) { + *pinctrl_dev = map->pinctrl_dev; + if (!pinctrl_dev) + return -1; + + if (map->pinctrl_group) + *id = map->pinctrl_group[offset + - map->gpio_pin]; + else + *id = map->pinctrl_pin + + (offset - map->gpio_pin); + + return 0; + } + } + + return -1; +} + +/** + * scmi_gpio_get_value - Get a value of a gpio pin + * @dev: SCMI gpio device + * @offset:Pin offset + * + * Get a value of a gpio pin in @offset + * + * Return: Value of a pin on success, error code on failure + */ +static int scmi_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct scmi_pinctrl_priv *priv; + u32 id; + struct udevice *pinctrl_dev; + struct scmi_pin_entry *config; + int config_type, ret; + + if (map_to_id(dev, offset, &pinctrl_dev, &id)) { + dev_err(dev, "Invalid pin: %u\n", offset); + return -EINVAL; + } + + priv = dev_get_priv(pinctrl_dev); + if (priv->pins[id].status[SCMI_PINCTRL_CONFIG_INPUT_MODE]) { + config_type = SCMI_PINCTRL_CONFIG_INPUT_VALUE; + } else if (priv->pins[id].status[SCMI_PINCTRL_CONFIG_OUTPUT_MODE]) { + config_type = SCMI_PINCTRL_CONFIG_OUTP
[RFC 5/6] firmware: scmi: add pseudo pinctrl protocol support on sandbox
With this patch, sandbox SCMI agent can handle pinctrl protocol. This feature is used in an unit test for SCMI pinctrl. Signed-off-by: AKASHI Takahiro --- arch/sandbox/dts/test.dts | 115 drivers/firmware/scmi/sandbox-scmi_agent.c | 722 + 2 files changed, 837 insertions(+) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dc0bfdfb6e4b..d2ddea801995 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -723,9 +723,124 @@ }; }; }; + + pinctrl_scmi: protocol@19 { + reg = <0x19>; + + pinctrl-names = "default","alternate"; + pinctrl-0 = <&scmi_pinctrl_gpios>, <&scmi_pinctrl_i2s>; + pinctrl-1 = <&scmi_pinctrl_spi>, <&scmi_pinctrl_i2c>; + +#if 0 + scmi_pinctrl_gpio_a: scmi_gpios { + gpio-controller; + #gpio-cells = <2>; + gpio-bank-name = "scmi_gpios"; + ngpios = <4>; + gpio-ranges = <&pinctrl_scmi 0 5 4>, + <&pinctrl_scmi 4 0 0>; + gpio-ranges-group-names = "", + "GPIO_B"; + + hog_input_1 { + gpio-hog; + input; + gpios = <1 GPIO_ACTIVE_HIGH>; + }; + hog_output_3 { + gpio-hog; + output-high; + output-mode; + output-value = <1>; + gpios = <3 GPIO_ACTIVE_HIGH>; + }; + }; +#endif + + scmi_pinctrl_gpios: gpios-pins { + gpio0 { + pins = "P5"; + function = "GPIO"; + bias-pull-up; + // input-disable; + input-mode = <0>; + }; + gpio1 { + pins = "P6"; + function = "GPIO"; + // output-high; + output-mode; + output-value = <1>; + drive-open-drain; + }; + gpio2 { + pinmux = ; + bias-pull-down; + // input-enable; + input-mode; + }; + gpio3 { + pinmux = ; + bias-disable; + }; + }; + + scmi_pinctrl_i2c: i2c-pins { + groups { + groups = "I2C_UART"; + function = "I2C"; + }; + + pins { + pins = "P0", "P1"; + drive-open-drain; + }; + }; + + scmi_pinctrl_i2s: i2s-pins { + groups = "SPI_I2S"; + function = "I2S"; + }; + +
[RFC 6/6] test: dm: add SCMI pinctrl test
In this test, SCMI-based pinmux feature is exercised. Signed-off-by: AKASHI Takahiro --- test/dm/scmi.c | 62 ++ 1 file changed, 62 insertions(+) diff --git a/test/dm/scmi.c b/test/dm/scmi.c index 423b6ef70b29..ca5a2e9c781e 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -395,3 +396,64 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) return release_sandbox_scmi_test_devices(uts, dev); } DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT); + +/* + * This part is derived from test/dm/pinmux.c, So + * + * Copyright (C) 2020 Sean Anderson + */ + +static char buf[64]; +#define test_muxing(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +#define test_name(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_name(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +static int dm_test_scmi_pinmux(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, "protocol@19", + &dev)); + ut_assertok(pinctrl_select_state(dev, "default")); + test_muxing(0, ""); + test_muxing(1, ""); + test_muxing(2, "I2S."); + test_muxing(3, "I2S."); + test_muxing(4, "I2S."); + test_muxing(5, "GPIO bias-pull-up."); + test_muxing(6, "GPIO drive-open-drain output-mode output-value."); + test_muxing(7, "GPIO bias-pull-down input-mode."); + test_muxing(8, "GPIO bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "alternate")); + test_muxing(0, "I2C drive-open-drain."); + test_muxing(1, "I2C drive-open-drain."); + test_muxing(2, "SPI."); + test_muxing(3, "SPI."); + test_muxing(4, "SPI."); + test_muxing(5, "CS bias-pull-up."); + test_muxing(6, "CS drive-open-drain output-mode output-value."); + test_muxing(7, "GPIO bias-pull-down input-mode."); + test_muxing(8, "GPIO bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "0")); + test_muxing(0, "I2C drive-open-drain."); + test_muxing(1, "I2C drive-open-drain."); + test_muxing(2, "I2S."); + test_muxing(3, "I2S."); + test_muxing(4, "I2S."); + test_muxing(5, "GPIO bias-pull-up."); + test_muxing(6, "GPIO drive-open-drain output-mode output-value."); + test_muxing(7, "GPIO bias-pull-down input-mode."); + test_muxing(8, "GPIO bias-disable."); + + return 0; +} + +DM_TEST(dm_test_scmi_pinmux, UT_TESTF_SCAN_FDT); -- 2.34.1
Re: [RFC] make sandbox UT more generic
Hi Simon, On Thu, Aug 31, 2023 at 09:04:43AM -0600, Simon Glass wrote: > Hi, > > On Wed, 30 Aug 2023 at 23:28, AKASHI Takahiro > wrote: > > > > Hi Simon, > > > > On Wed, Aug 30, 2023 at 08:49:05PM -0600, Simon Glass wrote: > > > Hi, > > > > > > On Wed, 30 Aug 2023 at 18:38, AKASHI Takahiro > > > wrote: > > > > > > > > Hi, > > > > > > > > I'm working on implementing SCMI-based pinctrl/gpio driver, > > > > and want to re-use sandbox UT to test the code. However, > > > > It is somehow sandbox-specific (with additional DT nodes). > > > > How can/should we make it more generic for other targets/drivers > > > > rather than just by copying the test code? > > > > (I have already created a test for pinmux since there is only > > > > one existing scenario, but gpio test has many.) > > > > > > > > Even if I say 'generic', my case may be special since real > > > > hardware (device drivers) cannot always run all the test cases, > > > > while SCMI-based drivers potentially can with a dummy SCMI server > > > > for sandbox. > > > > See: > > > > drivers/firmware/scmi/sandbox-scmi_agent.c > > > > > > We don't have a good way to test drivers that talk to hardware, in > > > general. > > > > > > For I2C, SPI and some PCI devices you can sometimes write an emulator > > > for the chip and then your driver can talk to the emulator as if it > > > were talking to the hardware. Sandbox does actually support that with > > > memory-mapped I/O too, although it is fairly rarely used. > > > > Well, I don't want or need to emulate some *real* hardware. > > Instead, I would like to emulate what the current sandbox drivers > > (pinctrl-sandbox.c and gpio/sandbox.c) emulate so that we can re-use > > (some portion of) test cases for sandbox (test/dm/pinmux.c and gpio.c). > > > > As you might know, SCMI protocol with associated drivers on U-Boot is > > so generic that it would be able to talk to any of real pinctrl/gpio > > drivers/firmware (say, run on OPTEE or SCP). > > By implementing/mimicking protocol messages in sandbox-scmi_agent.c, > > SCMI drivers are expected to provide *virtual* pinctrl/gpio devices > > similar to what sandbox does. > > I actually know almost nothing about SCMI. > > > > > I have already implemented pinmux test with some tweaks by copying > > test/dm/pinmux.c and duplicating almost the same DT nodes as "pinctrl-gpio" > > in test.dts. > > But I'm looking for any other means without test code duplication. > > > > Did I clarify my question a bit? > > Well you should be able to factor out the test code into a function, > then call it from two places with the two different devices (or other > params) that are needed. > > For the DT, copying a few nodes is not the end of the world, IMO. > > BTW have you seen this talk? [2] It seems that you are moving pieces > into firmware which should be OS drivers? > > Anyway, if you place a sandbox pinmux device under the SCMI node in > the DT, then you should end up with a pinmux device you can use likely > normal. Then if that device uses the sandbox emulator, you can run the > existing tests on it with little modification, I suspect. > > But if I am still missing the point, a diagram or patch might help me > understand! I just posted my RFC for supporting SCMI pinctrl protocol[1], hoping it will help you understand what I'm planning to do regarding test methodology, in particular by looking at patch#5 and #6. [1] https://lists.denx.de/pipermail/u-boot/2023-September/529765.html Thanks, -Takahiro Akashi > Regards, > Simon > > > > > > -Takahiro Akashi > > > > > > > We have done this a lot with Zephyr, as well[1] and achieved 90% code > > > coverage on some boards. > > > > > > But I'm not quite sure I am answering the right question, so I will stop > > > here. > > > > > > Regards, > > > Simon > > > > > > [1] https://www.youtube.com/watch?v=usXCAXR2G_c > > [2] https://www.usenix.org/conference/osdi21/presentation/fri-keynote
Re: [RFC 4/6] gpio: add scmi driver based on pinctrl
On Wed, Sep 06, 2023 at 04:56:56PM +0200, Michal Simek wrote: > > > On 9/6/23 04:40, AKASHI Takahiro wrote: > > This DM-compliant driver deals with SCMI pinctrl protocol and presents > > gpio devices exposed by SCMI firmware (server). > > > > Signed-off-by: AKASHI Takahiro > > --- > > drivers/pinctrl/pinctrl-scmi.c | 544 - > > 1 file changed, 539 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c > > index 3ebdad57b86c..73d385bdbfcc 100644 > > --- a/drivers/pinctrl/pinctrl-scmi.c > > +++ b/drivers/pinctrl/pinctrl-scmi.c > > @@ -11,21 +11,20 @@ > > #include > > #include > > #include > > +#include > > #include > > +#include > > +#include > > #include > > /** > >* struct scmi_pin - attributes for a pin > >* @name: Name of pin > > - * @value: Value of pin > > - * @flags: A set of flags > >* @function: Function selected > >* @status: An array of status of configuration types > >*/ > > struct scmi_pin { > > char*name; > > - u32 value; > > - u32 flags; > > > You have added this in 3/6 then there is no reason to remove it in this > version. Right. It was my mistake in a last-minute cleanup. The hunk should be merged in 3/6. BTW, this part of code, holding status of every pin's pinconf properties locally, is a bit clumsy. I'd remove the whole code if possible. -Takahiro Akashi > M
Re: [RFC 0/6] firmware: scmi: add SCMI pinctrl protocol support
Hi Peng, On Wed, Sep 06, 2023 at 12:09:45AM -0300, Fabio Estevam wrote: > Adding Peng Fan, who is working on scmi/pinctrl support for i.MX9: > > https://lore.kernel.org/all/ZO9GLG5tQynYyAvR@pluto/T/ I made a comment there. BTW, do you already have your own implementation of SCMI pin control protocol at SCMI firmware(server)? Is it public available? -Takahiro Akashi > On Tue, Sep 5, 2023 at 11:41 PM AKASHI Takahiro > wrote: > > > > This is an RFC and meant to get feedback from other developers as > > - the specification (pinctrl part) is still in a draft > > - the upstream patch for linux, including dt bindings, is still WIP > > - I'm not confident the drivers are generic enough to cover most HWs > > - The tests ("ut") doesn't cover all the features yet > > > > > > This patch series allows users to access SCMI pin control protocol provided > > by SCMI server (platform). See SCMI specification document v3.2 beta 2[1] > > for more details about SCMI pin control protocol. > > > > The implementation consists of two layers: > > - basic helper functions for SCMI pin control protocol > > in drivers/firmware/scmi/pinctrl.c (patch#2) > > - DM-compliant pinctrl/gpio drivers, which utilizes the helper functions, > > in drivers/pinctrl/pinctrl-scmi.c (patch#3,#4) > > > > [1] https://developer.arm.com/documentation/den0056/e/?lang=en > > > > DT bindings > > === > > Upstream pinctrl patch for linux defines the bindings in [2] though > > it doesn't say much. > > I expect that my implementation basically complies with U-Boot's generic > > bindings described in [3], but not all the features are verified. > > > > As for gpio, unless you hard-code pin assignments directly in a device > > driver, my implementation allows the following alternatives in DT. > > Either way, we may need an additional binding description for gpio. > > > > (A) > > scmi { > > ... // other protocols > > scmi_pinctrl: protocol@19 { // Pin control protocol > > ... > > {pinmux definitions}... // if any, including GPIO? > > } > > } > > scmi_gpio: scmi_gpio { > > compatible = "arm,scmi-gpio-generic"; > > gpio-controller; > > #gpio-cells = <2>; > > gpio-ranges = <&scmi_pinctrl 0 5 4>, > > <&scmi_pinctrl 4 0 0>; > > gpio-ranges-group-names = "", > > "ANOTHER_GPIO_GROUP"; > > } > > some_device { > > ... > > reset-gpios = <&scmi_gpio 0 GPIO_ACTIVE_HIGH>; > > } > > (B) > > scmi { > > ... // other protocols > > scmi_pinctrl: protocol@19 { // Pin control protocol > > ... > > {pinmux definitions}... // if any, including GPIO? > > > > scmi_gpio: scmi_gpio { > > // no need for "compatible" > > gpio-controller; > > #gpio-cells = <2>; > > gpio-ranges = <&scmi_pinctrl 0 5 4>, > > <&scmi_pinctrl 4 0 0>; > > gpio-ranges-group-names = "", > > "ANOTHER_GPIO_GROUP"; > > } > > } > > } > > some_device { > > ... > > reset-gpios = <&scmi_gpio 0 GPIO_ACTIVE_HIGH>; > > } > > (C) > > if "gpio-ranges" is missing in gpio definition, assume 1:1 mapping, > > i.e. use a native pinctrl pin number (5). > > some_device { > > ... > > reset-gpios = <&scmi_gpio 5 GPIO_ACTIVE_HIGH>; > > } > > > > > > [2] https://lkml.iu.edu/hypermail/linux/kernel/2308.1/01084.html > > [3] /doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt > > /doc/device-tree-bindings/gpio/gpio.txt > > > > Test > > > > The patch series was tested on the following platforms: > > * sandbox ("ut dm pinmux" and manually using gpio command) > > > > > > Prerequisite: > > = > > * This patch series is based on my WIP "Base protocol support" patches > > on v2023.10-rc3. You can fetch the whole code from [4]. > > > > [4] https://git.linaro.org/people/takahiro.akashi/u-boot.git > > branch:scmi/pinctrl > > > >
[PATCH v3 00/13] firmware: scmi: add SCMI base protocol support
This patch series allows users to access SCMI base protocol provided by SCMI server (platform). It will also be utilized in separate patches in the future to add sanity/validity checks for other protocols. See SCMI specification document v3.2 beta[1] for more details about SCMI base protocol. What is currently not implemented is - SCMI_BASE_NOTIFY_ERRORS command and notification callback mechanism This feature won't be very useful in the current U-Boot environment. [1] https://developer.arm.com/documentation/den0056/e/?lang=en Test The patch series was tested on the following platforms: * sandbox * qemu-arm64 with OPTEE as SCMI server Prerequisite: = * This patch series is based on v2023.10-rc3. Patches: Patch#1-#6: Add SCMI base protocol driver Patch#7-#10: Add SCMI base protocol device unit test Patch#11-#13: Add scmi command Change history: === v3 (Sep 8, 2023) * import patch#6 (protocol availability check) from my followup patch * fix an issue on ST board (reported by Etienne) (patch#1) * minor code improvements * fix various typos pointed out by Etienne * revise function descriptions/comments (Each commit message has more details.) v2 (Jul, 26, 2023) * refactor devm_scmi_of_get_channel()/process_msg(), removing uses of ops (patch#1) * use helper functions, removing uses of ops (patch#2,#9,#10) * add more descriptions in scmi command doc (patch#11) * remove 'scmi base' sub-command (patch#10,#12) v1 (Jun, 28, 2023) * initial release AKASHI Takahiro (13): scmi: refactor the code to hide a channel from devices firmware: scmi: implement SCMI base protocol firmware: scmi: move scmi_bind_protocols() backward firmware: scmi: framework for installing additional protocols firmware: scmi: install base protocol to SCMI agent firmware: scmi: add a check against availability of protocols sandbox: remove SCMI base node definition from test.dts firmware: scmi: fake base protocol commands on sandbox test: dm: simplify SCMI unit test on sandbox test: dm: add SCMI base protocol test cmd: add scmi command for SCMI firmware doc: cmd: add documentation for scmi test: dm: add scmi command test arch/sandbox/dts/test.dts | 4 - arch/sandbox/include/asm/scmi_test.h | 7 +- cmd/Kconfig| 9 + cmd/Makefile | 1 + cmd/scmi.c | 337 +++ doc/usage/cmd/scmi.rst | 126 drivers/clk/clk_scmi.c | 27 +- drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/base.c | 656 + drivers/firmware/scmi/sandbox-scmi_agent.c | 379 +++- drivers/firmware/scmi/scmi_agent-uclass.c | 416 +++-- drivers/power/regulator/scmi_regulator.c | 27 +- drivers/reset/reset-scmi.c | 19 +- include/dm/uclass-id.h | 1 + include/scmi_agent-uclass.h| 81 ++- include/scmi_agent.h | 29 +- include/scmi_protocols.h | 351 +++ test/dm/scmi.c | 228 +-- 18 files changed, 2506 insertions(+), 193 deletions(-) create mode 100644 cmd/scmi.c create mode 100644 doc/usage/cmd/scmi.rst create mode 100644 drivers/firmware/scmi/base.c -- 2.34.1
[PATCH v3 01/13] scmi: refactor the code to hide a channel from devices
The commit 85dc58289238 ("firmware: scmi: prepare uclass to pass channel reference") added an explicit parameter, channel, but it seems to make the code complex. Hiding this parameter will allow for adding a generic (protocol-agnostic) helper function, i.e. for PROTOCOL_VERSION, in a later patch. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass --- v3 * fix an issue on ST board (reported by Etienne) by taking care of cases where probed devices are children of SCMI protocol device (i.e. clock devices under CCF) See find_scmi_protocol_device(). * move "per_device_plato_auto" to a succeeding right patch v2 * new patch --- drivers/clk/clk_scmi.c| 27 +--- drivers/firmware/scmi/scmi_agent-uclass.c | 160 +++--- drivers/power/regulator/scmi_regulator.c | 27 +--- drivers/reset/reset-scmi.c| 19 +-- include/scmi_agent.h | 15 +- 5 files changed, 103 insertions(+), 145 deletions(-) diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index d172fed24c9d..34a49363a51a 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -13,17 +13,8 @@ #include #include -/** - * struct scmi_clk_priv - Private data for SCMI clocks - * @channel: Reference to the SCMI channel to use - */ -struct scmi_clk_priv { - struct scmi_channel *channel; -}; - static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) { - struct scmi_clk_priv *priv = dev_get_priv(dev); struct scmi_clk_protocol_attr_out out; struct scmi_msg msg = { .protocol_id = SCMI_PROTOCOL_ID_CLOCK, @@ -33,7 +24,7 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) }; int ret; - ret = devm_scmi_process_msg(dev, priv->channel, &msg); + ret = devm_scmi_process_msg(dev, &msg); if (ret) return ret; @@ -44,7 +35,6 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) { - struct scmi_clk_priv *priv = dev_get_priv(dev); struct scmi_clk_attribute_in in = { .clock_id = clkid, }; @@ -59,7 +49,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) }; int ret; - ret = devm_scmi_process_msg(dev, priv->channel, &msg); + ret = devm_scmi_process_msg(dev, &msg); if (ret) return ret; @@ -70,7 +60,6 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name) static int scmi_clk_gate(struct clk *clk, int enable) { - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); struct scmi_clk_state_in in = { .clock_id = clk->id, .attributes = enable, @@ -81,7 +70,7 @@ static int scmi_clk_gate(struct clk *clk, int enable) in, out); int ret; - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); + ret = devm_scmi_process_msg(clk->dev, &msg); if (ret) return ret; @@ -100,7 +89,6 @@ static int scmi_clk_disable(struct clk *clk) static ulong scmi_clk_get_rate(struct clk *clk) { - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); struct scmi_clk_rate_get_in in = { .clock_id = clk->id, }; @@ -110,7 +98,7 @@ static ulong scmi_clk_get_rate(struct clk *clk) in, out); int ret; - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); + ret = devm_scmi_process_msg(clk->dev, &msg); if (ret < 0) return ret; @@ -123,7 +111,6 @@ static ulong scmi_clk_get_rate(struct clk *clk) static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) { - struct scmi_clk_priv *priv = dev_get_priv(clk->dev); struct scmi_clk_rate_set_in in = { .clock_id = clk->id, .flags = SCMI_CLK_RATE_ROUND_CLOSEST, @@ -136,7 +123,7 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) in, out); int ret; - ret = devm_scmi_process_msg(clk->dev, priv->channel, &msg); + ret = devm_scmi_process_msg(clk->dev, &msg); if (ret < 0) return ret; @@ -149,12 +136,11 @@ static ulong scmi_clk_set_rate(struct clk *clk, ulong rate) static int scmi_clk_probe(struct udevice *dev) { - struct scmi_clk_priv *priv = dev_get_priv(dev); struct clk *clk; size_t num_clocks, i; int ret; - ret = devm_scmi_of_get_channel(dev, &priv->channel); + ret = devm_scmi_of_get_channel(dev); if (ret) return ret; @@ -205,5 +191,4 @@ U_BOOT_DRIVER(scmi_clo
[PATCH v3 02/13] firmware: scmi: implement SCMI base protocol
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 --- drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/base.c | 656 + include/dm/uclass-id.h | 1 + include/scmi_protocols.h | 351 ++ 4 files changed, 1009 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 ..6b99f36d0697 --- /dev/null +++ b/drivers/firmware/scmi/base.c @@ -0,0 +1,656 @@ +// 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 otherwise + */ +int scmi_generic_protocol_version(struct udevice *dev, + enum scmi_std_protocol id, u32 *version) +{ + struct scmi_protocol_version_out out; + struct scmi_msg msg = { + .protocol_id = id, + .message_id = SCMI_PROTOCOL_VERSION, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *version = out.version; + + return 0; +} + +/** + * scmi_base_protocol_version_int - get Base protocol version + * @dev: SCMI device + * @version: Pointer to SCMI protocol version + * + * Obtain the protocol version number in @version for Base protocol. + * + * Return: 0 on success, error code otherwise + */ +static int scmi_base_protocol_version_int(struct udevice *dev, u32 *version) +{ + return scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_BASE, +version); +} + +/** + * scmi_protocol_attrs_int - get protocol attributes + * @dev: SCMI device + * @num_agents:Number of SCMI agents + * @num_protocols: Number of SCMI protocols + * + * Obtain the protocol attributes, the number of agents and the number + * of protocols, in @num_agents and @num_protocols respectively, that + * the device provides. + * + * Return: 0 on success, error code otherwise + */ +static int scmi_protocol_attrs_int(struct udevice *dev, u32 *num_agents, + u32 *num_protocols) +{ + struct scmi_protocol_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_BASE, + .message_id = SCMI_PROTOCOL_ATTRIBUTES, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *num_agents = SCMI_PROTOCOL_ATTRS_NUM_AGENTS(out.attributes); + *num_protocols = SCMI_PROTOCOL_ATTRS_NUM_PROTOCOLS(out.attributes); + + return 0; +} + +/** + * scmi_protocol_message_attrs_int - get message-specific attributes + * @dev: SCMI device + * @message_id:SCMI message ID + * @attributes:Message-specific attributes + * + * Obtain the message-specific attributes in @attributes. + * This command succeeds if the message is implemented and available. + * + * Return: 0 on success, error code otherwise + */ +static int scmi_protocol_message_attrs_int(struct udevice
[PATCH v3 03/13] firmware: scmi: move scmi_bind_protocols() backward
Move the location of scmi_bind_protocols() backward for changes in later patches. There is no change in functionality. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere --- drivers/firmware/scmi/scmi_agent-uclass.c | 59 +++ 1 file changed, 59 insertions(+) diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index feb31809e715..94e54eeb066b 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -157,6 +157,65 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg) return scmi_process_msg(protocol->parent, priv->channel, msg); } +/* + * SCMI agent devices binds devices of various uclasses depeding on + * the FDT description. scmi_bind_protocol() is a generic bind sequence + * called by the uclass at bind stage, that is uclass post_bind. + */ +static int scmi_bind_protocols(struct udevice *dev) +{ + int ret = 0; + ofnode node; + const char *name; + + dev_for_each_subnode(node, dev) { + struct driver *drv = NULL; + u32 protocol_id; + + if (!ofnode_is_enabled(node)) + continue; + + if (ofnode_read_u32(node, "reg", &protocol_id)) + continue; + + name = ofnode_get_name(node); + switch (protocol_id) { + case SCMI_PROTOCOL_ID_CLOCK: + if (CONFIG_IS_ENABLED(CLK_SCMI)) + drv = DM_DRIVER_GET(scmi_clock); + break; + case SCMI_PROTOCOL_ID_RESET_DOMAIN: + if (IS_ENABLED(CONFIG_RESET_SCMI)) + drv = DM_DRIVER_GET(scmi_reset_domain); + break; + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: + 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; +} + UCLASS_DRIVER(scmi_agent) = { .id = UCLASS_SCMI_AGENT, .name = "scmi_agent", -- 2.34.1
[PATCH v3 04/13] firmware: scmi: framework for installing additional protocols
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; 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)) @@ -178,6 +260,7 @@ static int scmi_bind_protocols(struct udevice *dev) if (ofnode_read_u32(node, "reg", &protocol_id)) continue; + drv = NULL; name = ofnode_get_name(node); switch (protocol_id) { case SCMI_PROTOCOL_ID_CLOCK: @@ -208,11 +291,22 @@ static int scmi_bind_protocols(struct udevice *dev) continue; } - ret = device_bind(dev, drv, name, NULL, node, NULL); - if (ret) + ret = device_bind(dev, drv, name, NULL, node, &proto); + if (ret) { + dev_err(dev, "failed to bind %s protocol\n", drv->name); break; + } + ret = scmi_add_protocol(dev, protocol_id, proto); + if (ret) { + dev_err(dev, "failed to add protocol: %s, ret: %d\n", + proto->name, ret); +
[PATCH v3 05/13] firmware: scmi: install base protocol to SCMI agent
SCMI base protocol is mandatory, and once SCMI node is found in a device tree, the protocol handle (udevice) is unconditionally installed to the agent. Then basic information will be retrieved from SCMI server via the protocol and saved into the agent instance's local storage. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere --- v3 * typo fix: add '@' for argument name in function description * eliminate dev_get_uclass_plat()'s repeated in inline * modify the code for dynamically allocated sub-vendor/agent names v2 * use helper functions, removing direct uses of ops --- drivers/firmware/scmi/scmi_agent-uclass.c | 116 ++ include/scmi_agent-uclass.h | 66 2 files changed, 182 insertions(+) diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index e823d105a3eb..87a667d60124 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -57,6 +57,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev, } switch (id) { + case SCMI_PROTOCOL_ID_BASE: + proto = priv->base_dev; + break; case SCMI_PROTOCOL_ID_CLOCK: proto = priv->clock_dev; break; @@ -101,6 +104,9 @@ static int scmi_add_protocol(struct udevice *dev, } switch (proto_id) { + case SCMI_PROTOCOL_ID_BASE: + priv->base_dev = proto; + break; case SCMI_PROTOCOL_ID_CLOCK: priv->clock_dev = proto; break; @@ -237,6 +243,83 @@ int devm_scmi_process_msg(struct udevice *dev, struct scmi_msg *msg) return scmi_process_msg(protocol->parent, priv->channel, msg); } +/** + * scmi_fill_base_info - get base information about SCMI server + * @agent: SCMI agent device + * @dev: SCMI protocol device + * + * By using Base protocol commands, collect the base information + * about SCMI server. + * + * Return: 0 on success, error code otherwise + */ +static int scmi_fill_base_info(struct udevice *agent, struct udevice *dev) +{ + struct scmi_agent_priv *priv = dev_get_uclass_plat(agent); + int ret; + + ret = scmi_base_protocol_version(dev, &priv->version); + if (ret) { + dev_err(dev, "protocol_version() failed (%d)\n", ret); + return ret; + } + /* check for required version */ + if (priv->version < SCMI_BASE_PROTOCOL_VERSION) { + dev_err(dev, "base protocol version (%d) lower than expected\n", + priv->version); + return -EPROTO; + } + + ret = scmi_base_protocol_attrs(dev, &priv->num_agents, + &priv->num_protocols); + if (ret) { + dev_err(dev, "protocol_attrs() failed (%d)\n", ret); + return ret; + } + ret = scmi_base_discover_vendor(dev, &priv->vendor); + if (ret) { + dev_err(dev, "base_discover_vendor() failed (%d)\n", ret); + return ret; + } + ret = scmi_base_discover_sub_vendor(dev, &priv->sub_vendor); + if (ret) { + if (ret != -EOPNOTSUPP) { + dev_err(dev, "base_discover_sub_vendor() failed (%d)\n", + ret); + return ret; + } + priv->sub_vendor = "NA"; + } + ret = scmi_base_discover_impl_version(dev, &priv->impl_version); + if (ret) { + dev_err(dev, "base_discover_impl_version() failed (%d)\n", + ret); + return ret; + } + + priv->agent_id = 0x; /* to avoid false claim */ + ret = scmi_base_discover_agent(dev, 0x, + &priv->agent_id, &priv->agent_name); + if (ret) { + if (ret != -EOPNOTSUPP) { + dev_err(dev, + "base_discover_agent() failed for myself (%d)\n", + ret); + return ret; + } + priv->agent_name = "NA"; + } + + ret = scmi_base_discover_list_protocols(dev, &priv->protocols); + if (ret != priv->num_protocols) { + dev_err(dev, "base_discover_list_protocols() failed (%d)\n", + ret); + return ret; + } + + return 0; +} + /* * SCMI agent devices binds devices of various uclasses depeding on * the FDT description. scmi_bind_protocol() is a generic bind sequence @@ -251,6 +334,39 @@ static int scmi_bind_protocols(struct udevice
[PATCH v3 06/13] 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 --- v3 * new; import this patch from my followup patch set --- 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 87a667d60124..54e17992af00 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) { @@ -380,15 +412,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.34.1
[PATCH v3 07/13] sandbox: remove SCMI base node definition from test.dts
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 f351d5cb84b0..dc0bfdfb6e4b 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -693,10 +693,6 @@ #address-cells = <1>; #size-cells = <0>; - protocol@10 { - reg = <0x10>; - }; - clk_scmi: protocol@14 { reg = <0x14>; #clock-cells = <1>; -- 2.34.1
[PATCH v3 08/13] firmware: scmi: fake base protocol commands on sandbox
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 --- v3 * type fixes: s/udevice/dev/ in function descriptions --- 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..42a5a1f37f8b 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 + * @dev: SCMI device + * @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 + * @dev: 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 + * @dev: 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 <= SCMI_BASE_RESET_AGENT_CONFIGURATION && + message_id != SCMI_BASE_NOTIFY_ERRORS) { + out->attributes = 0; + out->status = SCMI_SUCCESS; + } else { + out->status = SCMI_NOT_FOUND; + } + + return 0; +} + +/** + * sandbox_scmi_base_discover_vendor - implement SCMI_BASE_DISCOVER_VENDOR + * @dev: SCMI device + * @msg: SCMI message + * + * Implement SCMI_BASE_DISCOVER_VENDOR command + */ +static int sandbox_scmi_base_discover_vendor(struct udevice *dev, +struct scmi_msg *msg) +{ + struct scmi_base_discover_vendor_out *out = NULL; + + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) + retu
[PATCH v3 09/13] test: dm: simplify SCMI unit test on sandbox
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 42a5a1f37f8b..27d17809be43 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -66,11 +66,9 @@ static struct sandbox_scmi_voltd scmi_voltd[] = { { .id = 1, .voltage_uv = 180 }, }; -static struct sandbox_scmi_service sandbox_scmi_service_state; - -struct sandbox_scmi_service *sandbox_scmi_service_ctx(void) +struct sandbox_scmi_agent *sandbox_scmi_agent_ctx(struct udevice *dev) { - return &sandbox_scmi_service_state; + return dev_get_priv(dev); } static void debug_print_agent_state(struct udevice *dev, char *str) @@ -898,16 +896,8 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, static int sandbox_scmi_test_remove(struct udevice *dev) { - struct sandbox_scmi_agent *agent = dev_get_priv(dev); - - if (agent != sandbox_scmi_service_ctx()->agent) - return -EINVAL; - debug_print_agent_state(dev, "removed"); - /* We only need to dereference the agent in the context */ - sandbox_scmi_service_ctx()->agent = NULL; - return 0; } @@ -915,9 +905,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev) { struct sandbox_scmi_agent *agent = dev_get_priv(dev); - if (sandbox_scmi_service_ctx()->agent) - return -EINVAL; - *agent = (struct sandbox_scmi_agent){ .clk = scmi_clk, .clk_count = ARRAY_SIZE(scmi_clk), @@ -929,9 +916,6 @@ static int sandbox_scmi_test_probe(struct udevice *dev) debug_print_agent_state(dev, "probed"); - /* Save reference for tests purpose */ - sandbox_scmi_service_ctx()->agent = agent; - return 0; }; diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 54e17992af00..b37acbb9f9db 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -455,9 +455,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 *scmi_ctx = sandbox_scmi_service_ctx(); - - ut_assertnonnull(scmi_ctx); - ut_assertnull(scmi_ctx->agent); - - return 0; -} - static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts, + struct sandbox_scmi_agent *agent, struct udevice *dev) { struct sandbox_scmi_devices *scmi_devices; - struct sandbox_scmi_service *scmi_ctx; - struct sandbox_scmi_agent *agent; /* Device references to check context against test sequence */ scmi_devices = sandbox_scmi_devices_ctx(dev); @@ -48,10 +37,6 @@ static int ut_assert_scmi_state_postprobe(struct unit
[PATCH v3 10/13] test: dm: add SCMI base protocol test
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 Reviewed-by: Etienne Carriere --- v3 * typo: s/scmi_base_protocol_attrs/scmi_base_protocol_message_attrs/ * modify the code for dynamically allocated vendor/agent names v2 * use helper functions, removing direct uses of ops --- test/dm/scmi.c | 112 + 1 file changed, 112 insertions(+) diff --git a/test/dm/scmi.c b/test/dm/scmi.c index 881be3171b7c..0785948186f0 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,115 @@ 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, *agent_name; + u8 *protocols; + int ret; + + /* preparation */ + ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi", + &agent_dev)); + ut_assertnonnull(agent_dev); + ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev)); + ut_assertnonnull(base = scmi_get_protocol(agent_dev, + SCMI_PROTOCOL_ID_BASE)); + + /* version */ + ret = scmi_base_protocol_version(base, &version); + ut_assertok(ret); + ut_asserteq(priv->version, version); + + /* protocol attributes */ + ret = scmi_base_protocol_attrs(base, &num_agents, &num_protocols); + 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); + free(vendor); + + /* message attributes */ + ret = scmi_protocol_message_attrs(base, + SCMI_BASE_DISCOVER_SUB_VENDOR, + &attributes); + ut_assertok(ret); + ut_assertok(attributes); + + /* discover sub vendor */ + ret = scmi_base_discover_sub_vendor(base, &vendor); + ut_assertok(ret); + ut_asserteq_str(priv->sub_vendor, vendor); + free(vendor); + + /* impl version */ + ret = scmi_base_discover_impl_version(base, &impl_version); + ut_assertok(ret); + ut_asserteq(priv->impl_version, impl_version); + + /* discover agent (my self) */ + ret = scmi_base_discover_agent(base, 0x, &agent_id, + &agent_name); + ut_assertok(ret); + ut_asserteq(priv->agent_id, agent_id); + ut_asserteq_str(priv->agent_name, agent_name); + free(agent_name); + + /* discover protocols */ + ret = scmi_base_discover_list_protocols(base, &protocols); + ut_asserteq(num_protocols, ret); + ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * num_protocols); + free(protocols); + + /* +* NOTE: Sandbox SCMI driver handles device-0 only. It supports setting +* access and protocol permissions, but doesn't allow unsetting them nor +* resetting the configurations. +*/ + /* set device permissions */ + ret = scmi_base_set_device_permissions(base, agent_id, 0, + SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS); + ut_assertok(ret); /* SCMI_SUCCESS */ + ret = scmi_base_set_device_permissions(base, agent_id, 1, + SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS); + ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */ + ret = scmi_base_set_device_permissions(base, agent_id, 0, 0); + ut_asserteq(-EACCES, ret); /* SCMI_DENIED */ + + /* set protocol permissions */ + ret = scmi_base_set_protocol_permissions(base, agent_id, 0, +SCMI_PROTOCOL_ID_CLOCK, + SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS); + ut_assertok(ret); /* SCMI_SUCCESS */ + ret = scmi_base_set_protocol_permissions(base, agent_id, 1, +SCMI_PROTOCOL_ID_CLOCK, + SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS); + ut_asserteq(-ENOENT, re
[PATCH v3 11/13] cmd: add scmi command for SCMI firmware
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 Reviewed-by: Simon Glass Reviewed-by: Etienne Carriere --- v3 * describe that arguments are in hex at a help message * modify the code for dynamically allocated agent names v2 * remove sub command category, 'scmi base', for simplicity --- cmd/Kconfig | 9 ++ cmd/Makefile | 1 + cmd/scmi.c | 337 +++ 3 files changed, 347 insertions(+) create mode 100644 cmd/scmi.c diff --git a/cmd/Kconfig b/cmd/Kconfig index 43ca10f69ccf..f46152ace7d8 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2533,6 +2533,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 9bebf321c397..ad3810b17e93 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -158,6 +158,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 ..5efec8ad87fd --- /dev/null +++ b/cmd/scmi.c @@ -0,0 +1,337 @@ +// 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 +#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, *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", scmi_num_agents(agent)); + for (i = 0; i < scmi_num_agents(agent); i++) { + ret = scmi_base_discover_agent(base_proto, i, &agent_id, + &agent_name); + if (ret) { + if (ret != -EOPNOTSUPP) + printf("base_discover_agent() failed for id: %d (%d)\n", + i, ret); + break; + } + printf("%c%2d: %s\n", i == scmi_agent_id(agent) ? '>' : ' ', +