[PATCH 8/8] misc: Add storage-by-uuid driver

Michael Olbrich mol at pengutronix.de
Tue Feb 8 01:29:31 PST 2022


On Mon, Feb 07, 2022 at 10:49:53AM +0100, Sascha Hauer wrote:
> This adds a driver which matches to a "barebox,storage-by-uuid"
> compatible node. The driver looks for a storage device matching the
> given UUID and when found registers a new cdev for the device.
> 
> This driver solved a very specific problem. On EFI the storage devices
> are not connected to any device tree node. barebox-state however expects
> a node to use as its backend. The obvious solution would be to create
> a partition with a specific partuuid and use that for state, in our
> special usecase though the storage device is partitioned with a MBR
> which doesn't have any space left to create a new partition. As this
> driver parses the of partition binding we can use that to create
> a partition in an unallocated are of the disk which is then used for
> state.
> 
> This driver has the problem that it depends on storage devices which
> are not described in the device tree. This means it cannot work with
> deep probe. This is not a problem on EFI though. It's a special purpose
> driver, it's not recommended for general use.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  drivers/misc/Kconfig           |  23 ++++
>  drivers/misc/Makefile          |   1 +
>  drivers/misc/storage-by-uuid.c | 199 +++++++++++++++++++++++++++++++++
>  3 files changed, 223 insertions(+)
>  create mode 100644 drivers/misc/storage-by-uuid.c
> 
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 5ab0506cd9..78c9c193d8 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -47,4 +47,27 @@ config STARFIVE_PWRSEQ
>  	  be accessed over /dev/mem or used from kernels which still depend
>  	  on bootloader for initialization.
>  
> +config STORAGE_BY_UUID
> +	bool "storage by UUID"
> +	depends on OFDEVICE
> +	help
> +	  This adds a driver which matches to a "barebox,storage-by-uuid"
> +	  compatible node. The driver looks for a storage device matching the
> +	  given UUID and when found registers a new cdev for the device.
> +
> +	  This driver solved a very specific problem. On EFI the storage devices
> +	  are not connected to any device tree node. barebox-state however expects
> +	  a node to use as its backend. The obvious solution would be to create
> +	  a partition with a specific partuuid and use that for state, in our
> +	  special usecase though the storage device is partitioned with a MBR
> +	  which doesn't have any space left to create a new partition. As this
> +	  driver parses the of partition binding we can use that to create
> +	  a partition in an unallocated are of the disk which is then used for
> +	  state.
> +
> +	  This driver has the problem that it depends on storage devices which
> +	  are not described in the device tree. This means it cannot work with
> +	  deep probe. This is not a problem on EFI though. It's a special purpose
> +	  driver, it's not recommended for general use.
> +
>  endmenu
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index 6326e784fc..986f7b1b38 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_STATE_DRV)		+= state.o
>  obj-$(CONFIG_DEV_MEM)		+= mem.o
>  obj-$(CONFIG_UBOOTVAR)		+= ubootvar.o
>  obj-$(CONFIG_STARFIVE_PWRSEQ)	+= starfive-pwrseq.o
> +obj-$(CONFIG_STORAGE_BY_UUID)	+= storage-by-uuid.o
> diff --git a/drivers/misc/storage-by-uuid.c b/drivers/misc/storage-by-uuid.c
> new file mode 100644
> index 0000000000..c9dd6e9793
> --- /dev/null
> +++ b/drivers/misc/storage-by-uuid.c
> @@ -0,0 +1,199 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +#include <common.h>
> +#include <init.h>
> +#include <io.h>
> +#include <of.h>
> +#include <malloc.h>
> +#include <partition.h>
> +#include <envfs.h>
> +#include <fs.h>
> +
> +static LIST_HEAD(sbu_list);
> +
> +struct sbu {
> +	char *uuid;
> +	struct device_d *dev;
> +	struct cdev *rcdev;
> +	struct cdev cdev;
> +	struct list_head list;
> +};
> +
> +void storage_by_uuid_check_exist(struct cdev *cdev);
> +
> +static ssize_t sbu_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_read(sbu->rcdev, buf, count, offset, flags);
> +}
> +
> +static ssize_t sbu_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_write(sbu->rcdev, buf, count, offset, flags);
> +}
> +
> +static int sbu_ioctl(struct cdev *cdev, int request, void *buf)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_ioctl(sbu->rcdev, request, buf);
> +}
> +
> +static int sbu_open(struct cdev *cdev, unsigned long flags)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_open(sbu->rcdev, flags);
> +}
> +
> +static int sbu_close(struct cdev *cdev)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	cdev_close(sbu->rcdev);
> +
> +	return 0;
> +}
> +
> +static int sbu_flush(struct cdev *cdev)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_flush(sbu->rcdev);
> +}
> +
> +static int sbu_erase(struct cdev *cdev, loff_t count, loff_t offset)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_erase(sbu->rcdev, count, offset);
> +}
> +
> +static int sbu_protect(struct cdev *cdev, size_t count, loff_t offset, int prot)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_protect(sbu->rcdev, count, offset, prot);
> +}
> +
> +static int sbu_discard_range(struct cdev *cdev, loff_t count, loff_t offset)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_discard_range(sbu->rcdev, count, offset);
> +}
> +
> +static int sbu_memmap(struct cdev *cdev, void **map, int flags)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_memmap(sbu->rcdev, map, flags);
> +}
> +
> +static int sbu_truncate(struct cdev *cdev, size_t size)
> +{
> +	struct sbu *sbu = cdev->priv;
> +
> +	return cdev_truncate(sbu->rcdev, size);
> +}
> +
> +static struct cdev_operations sbu_ops = {
> +        .read = sbu_read,
> +        .write = sbu_write,
> +        .ioctl = sbu_ioctl,
> +        .open = sbu_open,
> +        .close = sbu_close,
> +        .flush = sbu_flush,
> +        .erase = sbu_erase,
> +        .protect = sbu_protect,
> +        .discard_range = sbu_discard_range,
> +        .memmap = sbu_memmap,
> +        .truncate = sbu_truncate,

Should be indented with tabs, right?

Michael

> +};
> +
> +static void storage_by_uuid_add_partitions(struct sbu *sbu, struct cdev *rcdev)
> +{
> +	int ret;
> +
> +	if (sbu->rcdev)
> +		return;
> +
> +	sbu->rcdev = rcdev;
> +	sbu->cdev.name = sbu->uuid;
> +	sbu->cdev.size = rcdev->size;
> +	sbu->cdev.ops = &sbu_ops;
> +	sbu->cdev.dev = sbu->dev;
> +	sbu->cdev.priv = sbu;
> +
> +	ret = devfs_create(&sbu->cdev);
> +	if (ret) {
> +		dev_err(sbu->dev, "Failed to create cdev: %s\n", strerror(-ret));
> +		return;
> +	}
> +
> +	of_parse_partitions(&sbu->cdev, sbu->dev->device_node);
> +}
> +
> +static void check_exist(struct sbu *sbu)
> +{
> +	struct cdev *cdev;
> +
> +	for_each_cdev(cdev) {
> +		if (!strcmp(cdev->uuid, sbu->uuid)) {
> +			dev_dbg(sbu->dev, "Found %s %s\n", cdev->name, cdev->uuid);
> +			storage_by_uuid_add_partitions(sbu, cdev);
> +		}
> +	}
> +}
> +
> +static int sbu_detect(struct device_d *dev)
> +{
> +	struct sbu *sbu = dev->priv;
> +
> +	dev_dbg(dev, "%s\n", __func__);
> +
> +	check_exist(sbu);
> +
> +	return 0;
> +}
> +
> +static int storage_by_uuid_probe(struct device_d *dev)
> +{
> +	struct sbu *sbu;
> +	int ret;
> +	const char *uuid;
> +
> +	sbu = xzalloc(sizeof(*sbu));
> +
> +	ret = of_property_read_string(dev->device_node, "uuid", &uuid);
> +	if (ret)
> +		return ret;
> +
> +	sbu->dev = dev;
> +	sbu->uuid = xstrdup(uuid);
> +
> +	list_add_tail(&sbu->list, &sbu_list);
> +
> +	check_exist(sbu);
> +	dev->priv = sbu;
> +	dev->detect = sbu_detect;
> +
> +	return 0;
> +}
> +
> +static struct of_device_id storage_by_uuid_dt_ids[] = {
> +	{
> +		.compatible = "barebox,storage-by-uuid",
> +	}, {
> +		/* sentinel */
> +	}
> +};
> +
> +static struct driver_d storage_by_uuid_driver = {
> +	.name		= "storage-by-uuid",
> +	.probe		= storage_by_uuid_probe,
> +	.of_compatible	= storage_by_uuid_dt_ids,
> +};
> +device_platform_driver(storage_by_uuid_driver);
> -- 
> 2.30.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the barebox mailing list