diff options
author | Tom Rini <trini@konsulko.com> | 2023-04-05 18:59:47 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-04-05 18:59:47 -0400 |
commit | 487e42f7bc5e685c9337890a38358581bb4f31bc (patch) | |
tree | 03133e406371e92ce12b03b50c61a82637eea827 /doc/usage/blkmap.rst | |
parent | 25eeda170c5e533ca0e3837c8b2d7404cdd749d1 (diff) | |
parent | 272ec6b453049beaf0de6654dabf9bbd5f617022 (diff) |
Merge branch '2023-04-05-blkmap-composable-virtual-block-devices'
To quote the author:
Block maps are a way of looking at various sources of data through the
lens of a regular block device. It lets you treat devices that are not
block devices, like RAM, as if they were. It also lets you export a
slice of an existing block device, which does not have to correspond to
a partition boundary, as a new block device.
This is primarily useful because U-Boot's filesystem drivers only
operate on block devices, so a block map lets you access filesystems
wherever they might be located.
The implementation is loosely modeled on Linux's "Device Mapper"
subsystem, see the kernel documentation [1] for more information.
The primary use-cases are to access filesystem images stored in RAM, and
within FIT images stored on disk. See doc/usage/blkmap.rst for more
details.
The architecture is pluggable, so adding other types of mappings should
be quite easy.
[1]: https://docs.kernel.org/admin-guide/device-mapper/index.html
Diffstat (limited to 'doc/usage/blkmap.rst')
-rw-r--r-- | doc/usage/blkmap.rst | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/doc/usage/blkmap.rst b/doc/usage/blkmap.rst new file mode 100644 index 0000000000..dbfa8e5aad --- /dev/null +++ b/doc/usage/blkmap.rst @@ -0,0 +1,111 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. +.. Copyright (c) 2023 Addiva Elektronik +.. Author: Tobias Waldekranz <tobias@waldekranz.com> + +Block Maps (blkmap) +=================== + +Block maps are a way of looking at various sources of data through the +lens of a regular block device. It lets you treat devices that are not +block devices, like RAM, as if they were. It also lets you export a +slice of an existing block device, which does not have to correspond +to a partition boundary, as a new block device. + +This is primarily useful because U-Boot's filesystem drivers only +operate on block devices, so a block map lets you access filesystems +wherever they might be located. + +The implementation is loosely modeled on Linux's "Device Mapper" +subsystem, see `kernel documentation`_ for more information. + +.. _kernel documentation: https://docs.kernel.org/admin-guide/device-mapper/index.html + + +Example: Netbooting an Ext4 Image +--------------------------------- + +Say that our system is using an Ext4 filesystem as its rootfs, where +the kernel is stored in ``/boot``. This image is then typically stored +in an eMMC partition. In this configuration, we can use something like +``load mmc 0 ${kernel_addr_r} /boot/Image`` to load the kernel image +into the expected location, and then boot the system. No problems. + +Now imagine that during development, or as a recovery mechanism, we +want to boot the same type of image by downloading it over the +network. Getting the image to the target is easy enough: + +:: + + dhcp ${ramdisk_addr_r} rootfs.ext4 + +But now we are faced with a predicament: how to we extract the kernel +image? Block maps to the rescue! + +We start by creating a new device: + +:: + + blkmap create netboot + +Before setting up the mapping, we figure out the size of the +downloaded file, in blocks: + +:: + + setexpr fileblks ${filesize} + 0x1ff + setexpr fileblks ${filesize} / 0x200 + +Then we can add a mapping to the start of our device, backed by the +memory at `${loadaddr}`: + +:: + + blkmap map netboot 0 ${fileblks} mem ${fileaddr} + +Now we can access the filesystem via the virtual device: + +:: + + blkmap get netboot dev devnum + load blkmap ${devnum} ${kernel_addr_r} /boot/Image + + +Example: Accessing a filesystem inside an FIT image +--------------------------------------------------- + +In this example, an FIT image is stored in an eMMC partition. We would +like to read the file ``/etc/version``, stored inside a Squashfs image +in the FIT. Since the Squashfs image is not stored on a partition +boundary, there is no way of accessing it via ``load mmc ...``. + +What we can to instead is to first figure out the offset and size of +the filesystem: + +:: + + mmc dev 0 + mmc read ${loadaddr} 0 0x100 + + fdt addr ${loadaddr} + fdt get value squashaddr /images/ramdisk data-position + fdt get value squashsize /images/ramdisk data-size + + setexpr squashblk ${squashaddr} / 0x200 + setexpr squashsize ${squashsize} + 0x1ff + setexpr squashsize ${squashsize} / 0x200 + +Then we can create a block map that maps to that slice of the full +partition: + +:: + + blkmap create sq + blkmap map sq 0 ${squashsize} linear mmc 0 ${squashblk} + +Now we can access the filesystem: + +:: + + blkmap get sq dev devnum + load blkmap ${devnum} ${loadaddr} /etc/version |