diff options
Diffstat (limited to 'disk/disk-uclass.c')
-rw-r--r-- | disk/disk-uclass.c | 265 |
1 files changed, 80 insertions, 185 deletions
diff --git a/disk/disk-uclass.c b/disk/disk-uclass.c index d32747e2242..efe4bf1f949 100644 --- a/disk/disk-uclass.c +++ b/disk/disk-uclass.c @@ -17,227 +17,110 @@ #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) || !blk_enabled()) - 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 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; - - 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 part_blk_write(struct udevice *dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) +/** + * disk_blk_part_validate() - Check whether access to partition is within limits + * + * @dev: Device (partition udevice) + * @start: Start block for the access(from start of partition) + * @blkcnt: Number of blocks to access (within the partition) + * @return 0 on valid block range, or -ve on error. + */ +static int disk_blk_part_validate(struct udevice *dev, lbaint_t start, lbaint_t blkcnt) { - struct udevice *parent; - struct disk_part *part; - const struct blk_ops *ops; + struct disk_part *part = dev_get_uclass_plat(dev); - parent = dev_get_parent(dev); - ops = blk_get_ops(parent); - if (!ops->write) + if (device_get_uclass_id(dev) != UCLASS_PARTITION) return -ENOSYS; - part = dev_get_uclass_plat(dev); if (start >= part->gpt_part_info.size) - return 0; + return -E2BIG; if ((start + blkcnt) > part->gpt_part_info.size) - blkcnt = part->gpt_part_info.size - start; - start += part->gpt_part_info.start; + return -ERANGE; - return ops->write(parent, start, blkcnt, buffer); + return 0; } -static ulong part_blk_erase(struct udevice *dev, lbaint_t start, - lbaint_t blkcnt) +/** + * disk_blk_part_offset() - Compute offset from start of block device + * + * @dev: Device (partition udevice) + * @start: Start block for the access (from start of partition) + * @return Start block for the access (from start of block device) + */ +static lbaint_t disk_blk_part_offset(struct udevice *dev, lbaint_t start) { - 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; + struct disk_part *part = dev_get_uclass_plat(dev); - 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); + return start + part->gpt_part_info.start; } -static const struct blk_ops blk_part_ops = { - .read = part_blk_read, - .write = part_blk_write, - .erase = part_blk_erase, -}; - -U_BOOT_DRIVER(blk_partition) = { - .name = "blk_partition", - .id = UCLASS_PARTITION, - .ops = &blk_part_ops, -}; - /* * BLOCK IO APIs */ -static struct blk_desc *dev_get_blk(struct udevice *dev) -{ - struct blk_desc *desc; - - switch (device_get_uclass_id(dev)) { - /* - * We won't support UCLASS_BLK with dev_* interfaces. - */ - case UCLASS_PARTITION: - desc = dev_get_uclass_plat(dev_get_parent(dev)); - break; - default: - desc = NULL; - break; - } - - return desc; -} - +/** + * disk_blk_read() - Read from a block device partition + * + * @dev: Device to read from (partition udevice) + * @start: Start block for the read (from start of partition) + * @blkcnt: Number of blocks to read (within the partition) + * @buffer: Place to put the data + * @return number of blocks read (which may be less than @blkcnt), + * or -ve on error. This never returns 0 unless @blkcnt is 0 + */ unsigned long disk_blk_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buffer) { - struct blk_desc *desc; - const struct blk_ops *ops; - struct disk_part *part; - lbaint_t start_in_disk; - ulong blks_read; - - desc = dev_get_blk(dev); - if (!desc) - return -ENOSYS; + int ret = disk_blk_part_validate(dev, start, blkcnt); - ops = blk_get_ops(dev); - if (!ops->read) - return -ENOSYS; + if (ret) + return ret; - start_in_disk = start; - if (device_get_uclass_id(dev) == UCLASS_PARTITION) { - part = dev_get_uclass_plat(dev); - start_in_disk += part->gpt_part_info.start; - } - - if (blkcache_read(desc->uclass_id, desc->devnum, start_in_disk, blkcnt, - desc->blksz, buffer)) - return blkcnt; - blks_read = ops->read(dev, start, blkcnt, buffer); - if (blks_read == blkcnt) - blkcache_fill(desc->uclass_id, desc->devnum, start_in_disk, - blkcnt, desc->blksz, buffer); - - return blks_read; + return blk_read(dev_get_parent(dev), disk_blk_part_offset(dev, start), + blkcnt, buffer); } +/** + * disk_blk_write() - Write to a block device + * + * @dev: Device to write to (partition udevice) + * @start: Start block for the write (from start of partition) + * @blkcnt: Number of blocks to write (within the partition) + * @buffer: Data to write + * @return number of blocks written (which may be less than @blkcnt), + * or -ve on error. This never returns 0 unless @blkcnt is 0 + */ unsigned long disk_blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, const void *buffer) { - struct blk_desc *desc; - const struct blk_ops *ops; - - desc = dev_get_blk(dev); - if (!desc) - return -ENOSYS; - - ops = blk_get_ops(dev); - if (!ops->write) - return -ENOSYS; + int ret = disk_blk_part_validate(dev, start, blkcnt); - blkcache_invalidate(desc->uclass_id, desc->devnum); + if (ret) + return ret; - return ops->write(dev, start, blkcnt, buffer); + return blk_write(dev_get_parent(dev), disk_blk_part_offset(dev, start), + blkcnt, buffer); } +/** + * disk_blk_erase() - Erase part of a block device + * + * @dev: Device to erase (partition udevice) + * @start: Start block for the erase (from start of partition) + * @blkcnt: Number of blocks to erase (within the partition) + * @return number of blocks erased (which may be less than @blkcnt), + * or -ve on error. This never returns 0 unless @blkcnt is 0 + */ unsigned long disk_blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt) { - struct blk_desc *desc; - const struct blk_ops *ops; - - desc = dev_get_blk(dev); - if (!desc) - return -ENOSYS; + int ret = disk_blk_part_validate(dev, start, blkcnt); - ops = blk_get_ops(dev); - if (!ops->erase) - return -ENOSYS; - - blkcache_invalidate(desc->uclass_id, desc->devnum); + if (ret) + return ret; - return ops->erase(dev, start, blkcnt); + return blk_erase(dev_get_parent(dev), disk_blk_part_offset(dev, start), + blkcnt); } UCLASS_DRIVER(partition) = { @@ -245,3 +128,15 @@ UCLASS_DRIVER(partition) = { .per_device_plat_auto = sizeof(struct disk_part), .name = "partition", }; + +static const struct blk_ops blk_part_ops = { + .read = disk_blk_read, + .write = disk_blk_write, + .erase = disk_blk_erase, +}; + +U_BOOT_DRIVER(blk_partition) = { + .name = "blk_partition", + .id = UCLASS_PARTITION, + .ops = &blk_part_ops, +}; |