From 762dc78bdea3468e8cd35c01f91def13974948f1 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 16 Feb 2023 16:33:51 +0100 Subject: [PATCH] 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 Reviewed-by: Simon Glass --- drivers/block/blkmap.c | 71 ++++++++++++++++++++++++++++++++++++++++++ include/blkmap.h | 13 ++++++++ 2 files changed, 84 insertions(+) diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c index 6d6eed889e..2bb0acc20f 100644 --- a/drivers/block/blkmap.c +++ b/drivers/block/blkmap.c @@ -130,6 +130,77 @@ static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new) return 0; } +/** + * 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 * diff --git a/include/blkmap.h b/include/blkmap.h index 74baeb19f8..af54583c7d 100644 --- a/include/blkmap.h +++ b/include/blkmap.h @@ -7,6 +7,19 @@ #ifndef _BLKMAP_H #define _BLKMAP_H +/** + * blkmap_map_linear() - Map region of other block device + * + * @dev: Blkmap to create the mapping on + * @blknr: Start block number of the mapping + * @blkcnt: Number of blocks to map + * @lblk: The target block device of the mapping + * @lblknr: The start block number of the target device + * Returns: 0 on success, negative error code on failure + */ +int blkmap_map_linear(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + struct udevice *lblk, lbaint_t lblknr); + /** * blkmap_map_mem() - Map region of memory *