[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