diff options
author | Tobias Waldekranz <tobias@waldekranz.com> | 2023-02-16 16:33:50 +0100 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-04-05 10:54:47 -0400 |
commit | 15d9e99a274df5d9b260f75f42f7c394e5fe0e42 (patch) | |
tree | 21b128ef4330fc99ea0dde18b733d432da4b4ed5 /drivers/block | |
parent | c41e209ea67ee9be04519a3c7afda80a32253317 (diff) | |
download | u-boot-15d9e99a274df5d9b260f75f42f7c394e5fe0e42.zip u-boot-15d9e99a274df5d9b260f75f42f7c394e5fe0e42.tar.gz u-boot-15d9e99a274df5d9b260f75f42f7c394e5fe0e42.tar.bz2 |
blk: blkmap: Add memory mapping support
Allow a slice of RAM to be mapped to a blkmap. This means that RAM can
now be accessed as if it was a block device, meaning that existing
filesystem drivers can now be used to access ramdisks.
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 | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c index acfc002..6d6eed8 100644 --- a/drivers/block/blkmap.c +++ b/drivers/block/blkmap.c @@ -130,6 +130,111 @@ static int blkmap_slice_add(struct blkmap *bm, struct blkmap_slice *new) return 0; } +/** + * struct blkmap_mem - Memory mapping + * + * @slice: Common map data + * @addr: Target memory region of this mapping + * @remapped: True if @addr is backed by a physical to virtual memory + * mapping that must be torn down at the end of this mapping's + * lifetime. + */ +struct blkmap_mem { + struct blkmap_slice slice; + void *addr; + bool remapped; +}; + +static ulong blkmap_mem_read(struct blkmap *bm, struct blkmap_slice *bms, + lbaint_t blknr, lbaint_t blkcnt, void *buffer) +{ + struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice); + struct blk_desc *bd = dev_get_uclass_plat(bm->blk); + char *src; + + src = bmm->addr + (blknr << bd->log2blksz); + memcpy(buffer, src, blkcnt << bd->log2blksz); + return blkcnt; +} + +static ulong blkmap_mem_write(struct blkmap *bm, struct blkmap_slice *bms, + lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice); + struct blk_desc *bd = dev_get_uclass_plat(bm->blk); + char *dst; + + dst = bmm->addr + (blknr << bd->log2blksz); + memcpy(dst, buffer, blkcnt << bd->log2blksz); + return blkcnt; +} + +static void blkmap_mem_destroy(struct blkmap *bm, struct blkmap_slice *bms) +{ + struct blkmap_mem *bmm = container_of(bms, struct blkmap_mem, slice); + + if (bmm->remapped) + unmap_sysmem(bmm->addr); +} + +int __blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *addr, bool remapped) +{ + struct blkmap *bm = dev_get_plat(dev); + struct blkmap_mem *bmm; + int err; + + bmm = malloc(sizeof(*bmm)); + if (!bmm) + return -ENOMEM; + + *bmm = (struct blkmap_mem) { + .slice = { + .blknr = blknr, + .blkcnt = blkcnt, + + .read = blkmap_mem_read, + .write = blkmap_mem_write, + .destroy = blkmap_mem_destroy, + }, + + .addr = addr, + .remapped = remapped, + }; + + err = blkmap_slice_add(bm, &bmm->slice); + if (err) + free(bmm); + + return err; +} + +int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *addr) +{ + return __blkmap_map_mem(dev, blknr, blkcnt, addr, false); +} + +int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + phys_addr_t paddr) +{ + struct blkmap *bm = dev_get_plat(dev); + struct blk_desc *bd = dev_get_uclass_plat(bm->blk); + void *addr; + int err; + + addr = map_sysmem(paddr, blkcnt << bd->log2blksz); + if (!addr) + return -ENOMEM; + + err = __blkmap_map_mem(dev, blknr, blkcnt, addr, true); + if (err) + unmap_sysmem(addr); + + return err; +} + static ulong blkmap_blk_read_slice(struct blkmap *bm, struct blkmap_slice *bms, lbaint_t blknr, lbaint_t blkcnt, void *buffer) |