aboutsummaryrefslogtreecommitdiff
path: root/drivers/block
diff options
context:
space:
mode:
authorTobias Waldekranz <tobias@waldekranz.com>2023-02-16 16:33:51 +0100
committerTom Rini <trini@konsulko.com>2023-04-05 10:54:47 -0400
commit762dc78bdea3468e8cd35c01f91def13974948f1 (patch)
tree4bae2048970ae039b9a1f65ad527aafc48cdf31c /drivers/block
parent15d9e99a274df5d9b260f75f42f7c394e5fe0e42 (diff)
downloadu-boot-762dc78bdea3468e8cd35c01f91def13974948f1.zip
u-boot-762dc78bdea3468e8cd35c01f91def13974948f1.tar.gz
u-boot-762dc78bdea3468e8cd35c01f91def13974948f1.tar.bz2
blk: blkmap: Add linear device mapping support
Allow a slice of an existing block device to be mapped to a blkmap. This means that filesystems that are not stored at exact partition boundaries can be accessed by remapping a slice of the existing device to a blkmap device. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/blkmap.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c
index 6d6eed8..2bb0acc 100644
--- a/drivers/block/blkmap.c
+++ b/drivers/block/blkmap.c
@@ -131,6 +131,77 @@ static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new)
}
/**
+ * struct blkmap_linear - Linear mapping to other block device
+ *
+ * @slice: Common map data
+ * @blk: Target block device of this mapping
+ * @blknr: Start block number of the target device
+ */
+struct blkmap_linear {
+ struct blkmap_slice slice;
+
+ struct udevice *blk;
+ lbaint_t blknr;
+};
+
+static ulong blkmap_linear_read(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt, void *buffer)
+{
+ struct blkmap_linear *bml = container_of(bms, struct blkmap_linear, slice);
+
+ return blk_read(bml->blk, bml->blknr + blknr, blkcnt, buffer);
+}
+
+static ulong blkmap_linear_write(struct blkmap *bm, struct blkmap_slice *bms,
+ lbaint_t blknr, lbaint_t blkcnt,
+ const void *buffer)
+{
+ struct blkmap_linear *bml = container_of(bms, struct blkmap_linear, slice);
+
+ return blk_write(bml->blk, bml->blknr + blknr, blkcnt, buffer);
+}
+
+int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+ struct udevice *lblk, lbaint_t lblknr)
+{
+ struct blkmap *bm = dev_get_plat(dev);
+ struct blkmap_linear *linear;
+ struct blk_desc *bd, *lbd;
+ int err;
+
+ bd = dev_get_uclass_plat(bm->blk);
+ lbd = dev_get_uclass_plat(lblk);
+ if (lbd->blksz != bd->blksz)
+ /* We could support block size translation, but we
+ * don't yet.
+ */
+ return -EINVAL;
+
+ linear = malloc(sizeof(*linear));
+ if (!linear)
+ return -ENOMEM;
+
+ *linear = (struct blkmap_linear) {
+ .slice = {
+ .blknr = blknr,
+ .blkcnt = blkcnt,
+
+ .read = blkmap_linear_read,
+ .write = blkmap_linear_write,
+ },
+
+ .blk = lblk,
+ .blknr = lblknr,
+ };
+
+ err = blkmap_slice_add(bm, &linear->slice);
+ if (err)
+ free(linear);
+
+ return err;
+}
+
+/**
* struct blkmap_mem - Memory mapping
*
* @slice: Common map data