diff options
author | AKASHI Takahiro <takahiro.akashi@linaro.org> | 2022-04-19 10:05:09 +0900 |
---|---|---|
committer | Heinrich Schuchardt <heinrich.schuchardt@canonical.com> | 2022-04-23 22:05:41 +0200 |
commit | 43855fdb2c99eae0cdc9b3c54c2d719262d3b3eb (patch) | |
tree | 02cc726f5c18ca426a77453e411660da5383e2eb /disk | |
parent | 8ff50227befdc778eb2cb239b778ed1ed843bf33 (diff) | |
download | u-boot-43855fdb2c99eae0cdc9b3c54c2d719262d3b3eb.tar.gz |
dm: disk: add UCLASS_PARTITION
NOTE: probably we have to update config dependencies,
in particular, SPL/TPL_PRINTF?
With this new function, UCLASS_PARTITION devices will be created as
child nodes of UCLASS_BLK device.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Diffstat (limited to 'disk')
-rw-r--r-- | disk/Makefile | 3 | ||||
-rw-r--r-- | disk/disk-uclass.c | 153 |
2 files changed, 156 insertions, 0 deletions
diff --git a/disk/Makefile b/disk/Makefile index 5ca10c55762..ec148832b33 100644 --- a/disk/Makefile +++ b/disk/Makefile @@ -6,6 +6,9 @@ #ccflags-y += -DET_DEBUG -DDEBUG obj-$(CONFIG_$(SPL_TPL_)PARTITIONS) += part.o +ifdef CONFIG_$(SPL_TPL_)BLK +obj-$(CONFIG_$(SPL_TPL_)PARTITIONS) += disk-uclass.o +endif obj-$(CONFIG_$(SPL_TPL_)MAC_PARTITION) += part_mac.o obj-$(CONFIG_$(SPL_TPL_)DOS_PARTITION) += part_dos.o obj-$(CONFIG_$(SPL_TPL_)ISO_PARTITION) += part_iso.o diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c new file mode 100644 index 00000000000..4918a2f72d1 --- /dev/null +++ b/disk/disk-uclass.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Software partition device (UCLASS_PARTITION) + * + * Copyright (c) 2021 Linaro Limited + * Author: AKASHI Takahiro + */ + +#define LOG_CATEGORY UCLASS_PARTITION + +#include <blk.h> +#include <dm.h> +#include <log.h> +#include <part.h> +#include <vsprintf.h> +#include <dm/device-internal.h> +#include <dm/lists.h> + +int part_create_block_devices(struct udevice *blk_dev) +{ + int part, count; + struct blk_desc *desc = dev_get_uclass_plat(blk_dev); + struct disk_partition info; + struct disk_part *part_data; + char devname[32]; + struct udevice *dev; + int ret; + + if (!CONFIG_IS_ENABLED(PARTITIONS) || + !CONFIG_IS_ENABLED(HAVE_BLOCK_DEVICE)) + return 0; + + if (device_get_uclass_id(blk_dev) != UCLASS_BLK) + return 0; + + /* Add devices for each partition */ + for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { + if (part_get_info(desc, part, &info)) + continue; + snprintf(devname, sizeof(devname), "%s:%d", blk_dev->name, + part); + + ret = device_bind_driver(blk_dev, "blk_partition", + strdup(devname), &dev); + if (ret) + return ret; + + part_data = dev_get_uclass_plat(dev); + part_data->partnum = part; + part_data->gpt_part_info = info; + count++; + + ret = device_probe(dev); + if (ret) { + debug("Can't probe\n"); + count--; + device_unbind(dev); + + continue; + } + } + debug("%s: %d partitions found in %s\n", __func__, count, + blk_dev->name); + + return 0; +} + +static ulong blk_part_read(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + 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) + 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->read(parent, start, blkcnt, buffer); +} + +static ulong blk_part_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; + + 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) + 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); +} + +static ulong blk_part_erase(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt) +{ + struct udevice *parent; + struct disk_part *part; + const struct blk_ops *ops; + + 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) + 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); +} + +static const struct blk_ops blk_part_ops = { + .read = blk_part_read, + .write = blk_part_write, + .erase = blk_part_erase, +}; + +U_BOOT_DRIVER(blk_partition) = { + .name = "blk_partition", + .id = UCLASS_PARTITION, + .ops = &blk_part_ops, +}; + +UCLASS_DRIVER(partition) = { + .id = UCLASS_PARTITION, + .per_device_plat_auto = sizeof(struct disk_part), + .name = "partition", +}; |