diff options
author | Tobias Waldekranz <tobias@waldekranz.com> | 2023-02-16 16:33:51 +0100 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-04-05 10:54:47 -0400 |
commit | 762dc78bdea3468e8cd35c01f91def13974948f1 (patch) | |
tree | 4bae2048970ae039b9a1f65ad527aafc48cdf31c /drivers/block | |
parent | 15d9e99a274df5d9b260f75f42f7c394e5fe0e42 (diff) | |
download | u-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.c | 71 |
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 |