Message ID | 20220202010853.40405-10-takahiro.akashi@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | efi_loader: more tightly integrate UEFI disks to driver model | expand |
On 2/2/22 02:08, AKASHI Takahiro wrote: > With dm-tag feature, any U-Boot subsystem is allowed to associate > arbitrary number of data with a particular udevice. This can been > see as expanding "struct udevice" without modifying the definition. > > As a first user, UEFI subsystem makes use of tags to associate > an efi_disk object with a block device. > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> > --- > drivers/core/Makefile | 2 +- > drivers/core/root.c | 2 + > drivers/core/tag.c | 139 ++++++++++++++++++++++++++++++ > include/asm-generic/global_data.h | 1 + > include/dm/tag.h | 110 +++++++++++++++++++++++ > 5 files changed, 253 insertions(+), 1 deletion(-) > create mode 100644 drivers/core/tag.c > create mode 100644 include/dm/tag.h > > diff --git a/drivers/core/Makefile b/drivers/core/Makefile > index 5edd4e413576..3742e7574525 100644 > --- a/drivers/core/Makefile > +++ b/drivers/core/Makefile > @@ -2,7 +2,7 @@ > # > # Copyright (c) 2013 Google, Inc > > -obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o > +obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o tag.o > obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o > obj-$(CONFIG_DEVRES) += devres.o > obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o > diff --git a/drivers/core/root.c b/drivers/core/root.c > index e3f87956d866..1aa4819ceb6c 100644 > --- a/drivers/core/root.c > +++ b/drivers/core/root.c > @@ -199,6 +199,8 @@ int dm_init(bool of_live) > return ret; > } > > + INIT_LIST_HEAD((struct list_head *)&gd->dmtag_list); > + > return 0; > } > > diff --git a/drivers/core/tag.c b/drivers/core/tag.c > new file mode 100644 > index 000000000000..6829bcd8806c > --- /dev/null > +++ b/drivers/core/tag.c > @@ -0,0 +1,139 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (c) 2021 Linaro Limited > + * Author: AKASHI Takahiro > + */ > + > +#include <malloc.h> > +#include <asm/global_data.h> > +#include <dm/tag.h> > +#include <linux/err.h> > +#include <linux/list.h> > +#include <linux/types.h> > + > +struct udevice; > + > +DECLARE_GLOBAL_DATA_PTR; > + > +int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr) > +{ > + struct dmtag_node *node; > + > + if (!dev || tag >= DM_TAG_COUNT) > + return -EINVAL; > + > + list_for_each_entry(node, &gd->dmtag_list, sibling) { > + if (node->dev == dev && node->tag == tag) > + return -EEXIST; > + } > + > + node = calloc(sizeof(*node), 1); > + if (!node) > + return -ENOSPC; > + > + node->dev = dev; > + node->tag = tag; > + node->ptr = ptr; > + list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list); > + > + return 0; > +} > + > +int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val) > +{ > + struct dmtag_node *node; > + > + if (!dev || tag >= DM_TAG_COUNT) > + return -EINVAL; > + > + list_for_each_entry(node, &gd->dmtag_list, sibling) { > + if (node->dev == dev && node->tag == tag) > + return -EEXIST; > + } > + > + node = calloc(sizeof(*node), 1); > + if (!node) > + return -ENOSPC; > + > + node->dev = dev; > + node->tag = tag; > + node->val = val; > + list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list); > + > + return 0; > +} > + > +int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp) > +{ > + struct dmtag_node *node; > + > + if (!dev || tag >= DM_TAG_COUNT) > + return -EINVAL; > + > + list_for_each_entry(node, &gd->dmtag_list, sibling) { > + if (node->dev == dev && node->tag == tag) { > + *ptrp = node->ptr; > + return 0; > + } > + } > + > + return -ENOENT; > +} > + > +int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp) > +{ > + struct dmtag_node *node; > + > + if (!dev || tag >= DM_TAG_COUNT) > + return -EINVAL; > + > + list_for_each_entry(node, &gd->dmtag_list, sibling) { > + if (node->dev == dev && node->tag == tag) { > + *valp = node->val; > + return 0; > + } > + } > + > + return -ENOENT; > +} > + > +int dev_tag_del(struct udevice *dev, enum dm_tag_t tag) > +{ > + struct dmtag_node *node, *tmp; > + > + if (!dev || tag >= DM_TAG_COUNT) > + return -EINVAL; > + > + list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) { > + if (node->dev == dev && node->tag == tag) { > + list_del(&node->sibling); > + free(node); > + > + return 0; > + } > + } > + > + return -ENOENT; > +} > + > +int dev_tag_del_all(struct udevice *dev) > +{ > + struct dmtag_node *node, *tmp; > + bool found = false; > + > + if (!dev) > + return -EINVAL; > + > + list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) { > + if (node->dev == dev) { > + list_del(&node->sibling); > + free(node); > + found = true; > + } > + } > + > + if (found) > + return 0; > + > + return -ENOENT; > +} > diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h > index 9f4598f09ee5..b887bef6deef 100644 > --- a/include/asm-generic/global_data.h > +++ b/include/asm-generic/global_data.h > @@ -470,6 +470,7 @@ struct global_data { > #if CONFIG_IS_ENABLED(EVENT) > struct event_state *event_state; > #endif > + struct list_head dmtag_list; This breaks 'make htmldocs'. You have to describe the new element. Best regards Heinrich > }; > #ifndef DO_DEPS_ONLY > static_assert(sizeof(struct global_data) == GD_SIZE); > diff --git a/include/dm/tag.h b/include/dm/tag.h > new file mode 100644 > index 000000000000..54fc31eb1539 > --- /dev/null > +++ b/include/dm/tag.h > @@ -0,0 +1,110 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Copyright (c) 2021 Linaro Limited > + * Author: AKASHI Takahiro > + */ > + > +#ifndef _DM_TAG_H > +#define _DM_TAG_H > + > +#include <linux/list.h> > +#include <linux/types.h> > + > +struct udevice; > + > +enum dm_tag_t { > + /* EFI_LOADER */ > + DM_TAG_EFI = 0, > + > + DM_TAG_COUNT, > +}; > + > +/** > + * dmtag_node > + * > + * @sibling: List of dm-tag nodes > + * @dev: Associated udevice > + * @tag: Tag type > + * @ptr: Pointer as a value > + * @val: Value > + */ > +struct dmtag_node { > + struct list_head sibling; > + struct udevice *dev; > + enum dm_tag_t tag; > + union { > + void *ptr; > + ulong val; > + }; > +}; > + > +/** > + * dev_tag_set_ptr() - set a tag's value as a pointer > + * @dev: Device to operate > + * @tag: Tag type > + * @ptr: Pointer to set > + * > + * Set the value, @ptr, as of @tag associated with the device, @dev > + * > + * Return: 0 on success, -ve on error > + */ > +int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr); > + > +/** > + * dev_tag_set_val() set a tag's value as an integer > + * @dev: Device to operate > + * @tag: Tag type > + * @val: Value to set > + * > + * Set the value, @val, as of @tag associated with the device, @dev > + * > + * Return: on success, -ve on error > + */ > +int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val); > + > +/** > + * dev_tag_get_ptr() - get a tag's value as a pointer > + * @dev: Device to operate > + * @tag: Tag type > + * @ptrp: Pointer to tag's value (pointer) > + * > + * Get a tag's value as a pointer > + * > + * Return: on success, -ve on error > + */ > +int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp); > + > +/** > + * dev_tag_get_val() - get a tag's value as an integer > + * @dev: Device to operate > + * @tag: Tag type > + * @valp: Pointer to tag's value (ulong) > + * > + * Get a tag's value as an integer > + * > + * Return: 0 on success, -ve on error > + */ > +int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp); > + > +/** > + * dev_tag_del() - delete a tag > + * @dev: Device to operate > + * @tag: Tag type > + * > + * Delete a tag of @tag associated with the device, @dev > + * > + * Return: 0 on success, -ve on error > + */ > +int dev_tag_del(struct udevice *dev, enum dm_tag_t tag); > + > +/** > + * dev_tag_del_all() - delete all tags > + * @dev: Device to operate > + * > + * Delete all the tags associated with the device, @dev > + * > + * Return: 0 on success, -ve on error > + */ > +int dev_tag_del_all(struct udevice *dev); > + > +#endif /* _DM_TAG_H */
diff --git a/drivers/core/Makefile b/drivers/core/Makefile index 5edd4e413576..3742e7574525 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -2,7 +2,7 @@ # # Copyright (c) 2013 Google, Inc -obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o +obj-y += device.o fdtaddr.o lists.o root.o uclass.o util.o tag.o obj-$(CONFIG_$(SPL_TPL_)ACPIGEN) += acpi.o obj-$(CONFIG_DEVRES) += devres.o obj-$(CONFIG_$(SPL_)DM_DEVICE_REMOVE) += device-remove.o diff --git a/drivers/core/root.c b/drivers/core/root.c index e3f87956d866..1aa4819ceb6c 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -199,6 +199,8 @@ int dm_init(bool of_live) return ret; } + INIT_LIST_HEAD((struct list_head *)&gd->dmtag_list); + return 0; } diff --git a/drivers/core/tag.c b/drivers/core/tag.c new file mode 100644 index 000000000000..6829bcd8806c --- /dev/null +++ b/drivers/core/tag.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include <malloc.h> +#include <asm/global_data.h> +#include <dm/tag.h> +#include <linux/err.h> +#include <linux/list.h> +#include <linux/types.h> + +struct udevice; + +DECLARE_GLOBAL_DATA_PTR; + +int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr) +{ + struct dmtag_node *node; + + if (!dev || tag >= DM_TAG_COUNT) + return -EINVAL; + + list_for_each_entry(node, &gd->dmtag_list, sibling) { + if (node->dev == dev && node->tag == tag) + return -EEXIST; + } + + node = calloc(sizeof(*node), 1); + if (!node) + return -ENOSPC; + + node->dev = dev; + node->tag = tag; + node->ptr = ptr; + list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list); + + return 0; +} + +int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val) +{ + struct dmtag_node *node; + + if (!dev || tag >= DM_TAG_COUNT) + return -EINVAL; + + list_for_each_entry(node, &gd->dmtag_list, sibling) { + if (node->dev == dev && node->tag == tag) + return -EEXIST; + } + + node = calloc(sizeof(*node), 1); + if (!node) + return -ENOSPC; + + node->dev = dev; + node->tag = tag; + node->val = val; + list_add_tail(&node->sibling, (struct list_head *)&gd->dmtag_list); + + return 0; +} + +int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp) +{ + struct dmtag_node *node; + + if (!dev || tag >= DM_TAG_COUNT) + return -EINVAL; + + list_for_each_entry(node, &gd->dmtag_list, sibling) { + if (node->dev == dev && node->tag == tag) { + *ptrp = node->ptr; + return 0; + } + } + + return -ENOENT; +} + +int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp) +{ + struct dmtag_node *node; + + if (!dev || tag >= DM_TAG_COUNT) + return -EINVAL; + + list_for_each_entry(node, &gd->dmtag_list, sibling) { + if (node->dev == dev && node->tag == tag) { + *valp = node->val; + return 0; + } + } + + return -ENOENT; +} + +int dev_tag_del(struct udevice *dev, enum dm_tag_t tag) +{ + struct dmtag_node *node, *tmp; + + if (!dev || tag >= DM_TAG_COUNT) + return -EINVAL; + + list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) { + if (node->dev == dev && node->tag == tag) { + list_del(&node->sibling); + free(node); + + return 0; + } + } + + return -ENOENT; +} + +int dev_tag_del_all(struct udevice *dev) +{ + struct dmtag_node *node, *tmp; + bool found = false; + + if (!dev) + return -EINVAL; + + list_for_each_entry_safe(node, tmp, &gd->dmtag_list, sibling) { + if (node->dev == dev) { + list_del(&node->sibling); + free(node); + found = true; + } + } + + if (found) + return 0; + + return -ENOENT; +} diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 9f4598f09ee5..b887bef6deef 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -470,6 +470,7 @@ struct global_data { #if CONFIG_IS_ENABLED(EVENT) struct event_state *event_state; #endif + struct list_head dmtag_list; }; #ifndef DO_DEPS_ONLY static_assert(sizeof(struct global_data) == GD_SIZE); diff --git a/include/dm/tag.h b/include/dm/tag.h new file mode 100644 index 000000000000..54fc31eb1539 --- /dev/null +++ b/include/dm/tag.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Linaro Limited + * Author: AKASHI Takahiro + */ + +#ifndef _DM_TAG_H +#define _DM_TAG_H + +#include <linux/list.h> +#include <linux/types.h> + +struct udevice; + +enum dm_tag_t { + /* EFI_LOADER */ + DM_TAG_EFI = 0, + + DM_TAG_COUNT, +}; + +/** + * dmtag_node + * + * @sibling: List of dm-tag nodes + * @dev: Associated udevice + * @tag: Tag type + * @ptr: Pointer as a value + * @val: Value + */ +struct dmtag_node { + struct list_head sibling; + struct udevice *dev; + enum dm_tag_t tag; + union { + void *ptr; + ulong val; + }; +}; + +/** + * dev_tag_set_ptr() - set a tag's value as a pointer + * @dev: Device to operate + * @tag: Tag type + * @ptr: Pointer to set + * + * Set the value, @ptr, as of @tag associated with the device, @dev + * + * Return: 0 on success, -ve on error + */ +int dev_tag_set_ptr(struct udevice *dev, enum dm_tag_t tag, void *ptr); + +/** + * dev_tag_set_val() set a tag's value as an integer + * @dev: Device to operate + * @tag: Tag type + * @val: Value to set + * + * Set the value, @val, as of @tag associated with the device, @dev + * + * Return: on success, -ve on error + */ +int dev_tag_set_val(struct udevice *dev, enum dm_tag_t tag, ulong val); + +/** + * dev_tag_get_ptr() - get a tag's value as a pointer + * @dev: Device to operate + * @tag: Tag type + * @ptrp: Pointer to tag's value (pointer) + * + * Get a tag's value as a pointer + * + * Return: on success, -ve on error + */ +int dev_tag_get_ptr(struct udevice *dev, enum dm_tag_t tag, void **ptrp); + +/** + * dev_tag_get_val() - get a tag's value as an integer + * @dev: Device to operate + * @tag: Tag type + * @valp: Pointer to tag's value (ulong) + * + * Get a tag's value as an integer + * + * Return: 0 on success, -ve on error + */ +int dev_tag_get_val(struct udevice *dev, enum dm_tag_t tag, ulong *valp); + +/** + * dev_tag_del() - delete a tag + * @dev: Device to operate + * @tag: Tag type + * + * Delete a tag of @tag associated with the device, @dev + * + * Return: 0 on success, -ve on error + */ +int dev_tag_del(struct udevice *dev, enum dm_tag_t tag); + +/** + * dev_tag_del_all() - delete all tags + * @dev: Device to operate + * + * Delete all the tags associated with the device, @dev + * + * Return: 0 on success, -ve on error + */ +int dev_tag_del_all(struct udevice *dev); + +#endif /* _DM_TAG_H */
With dm-tag feature, any U-Boot subsystem is allowed to associate arbitrary number of data with a particular udevice. This can been see as expanding "struct udevice" without modifying the definition. As a first user, UEFI subsystem makes use of tags to associate an efi_disk object with a block device. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> --- drivers/core/Makefile | 2 +- drivers/core/root.c | 2 + drivers/core/tag.c | 139 ++++++++++++++++++++++++++++++ include/asm-generic/global_data.h | 1 + include/dm/tag.h | 110 +++++++++++++++++++++++ 5 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 drivers/core/tag.c create mode 100644 include/dm/tag.h