]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
blk: blkmap: Add memory mapping support
authorTobias Waldekranz <tobias@waldekranz.com>
Thu, 16 Feb 2023 15:33:50 +0000 (16:33 +0100)
committerTom Rini <trini@konsulko.com>
Wed, 5 Apr 2023 14:54:47 +0000 (10:54 -0400)
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>
drivers/block/blkmap.c
include/blkmap.h

index acfc002ceba4d81b5861256622d197ec51be6cc5..6d6eed889e35b0a4bcbe44d51e74c083a8a3411d 100644 (file)
@@ -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)
index 3c7e36efabcfc06a74326f21271dda3a9760c0cf..74baeb19f8135db9561e2cd35c04dac93d0bf8c3 100644 (file)
@@ -7,6 +7,35 @@
 #ifndef _BLKMAP_H
 #define _BLKMAP_H
 
+/**
+ * blkmap_map_mem() - Map region of memory
+ *
+ * @dev: Blkmap to create the mapping on
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks to map
+ * @addr: The target memory address of the mapping
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_map_mem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+                  void *addr);
+
+/**
+ * blkmap_map_pmem() - Map region of physical memory
+ *
+ * Ensures that a valid physical to virtual memory mapping for the
+ * requested region is valid for the lifetime of the mapping, on
+ * architectures that require it (sandbox).
+ *
+ * @dev: Blkmap to create the mapping on
+ * @blknr: Start block number of the mapping
+ * @blkcnt: Number of blocks to map
+ * @paddr: The target physical memory address of the mapping
+ * Returns: 0 on success, negative error code on failure
+ */
+int blkmap_map_pmem(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
+                   phys_addr_t paddr);
+
+
 /**
  * blkmap_from_label() - Find blkmap from label
  *