From e3e5487b849239f1a108ae2d475046068b5291b6 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Thu, 16 Feb 2023 16:33:54 +0100 Subject: [PATCH] doc: blkmap: Add introduction and examples Explain block maps by going through two common use-cases. Signed-off-by: Tobias Waldekranz Reviewed-by: Simon Glass --- MAINTAINERS | 1 + doc/usage/blkmap.rst | 111 +++++++++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + 3 files changed, 113 insertions(+) create mode 100644 doc/usage/blkmap.rst diff --git a/MAINTAINERS b/MAINTAINERS index ec8b149ce7..4c17c6cb9f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -797,6 +797,7 @@ BLKMAP M: Tobias Waldekranz S: Maintained F: cmd/blkmap.c +F: doc/usage/blkmap.rst F: drivers/block/blkmap.c F: include/blkmap.h F: test/dm/blkmap.c 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 + +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 diff --git a/doc/usage/index.rst b/doc/usage/index.rst index bc85e1d49a..729541bcff 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -4,6 +4,7 @@ Use U-Boot .. toctree:: :maxdepth: 1 + blkmap dfu environment fdt_overlays -- 2.39.5