.. 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