1.. SPDX-License-Identifier: GPL-2.0+ 2.. 3.. Copyright (c) 2023 Addiva Elektronik 4.. Author: Tobias Waldekranz <tobias@waldekranz.com> 5 6Block Maps (blkmap) 7=================== 8 9Block maps are a way of looking at various sources of data through the 10lens of a regular block device. It lets you treat devices that are not 11block devices, like RAM, as if they were. It also lets you export a 12slice of an existing block device, which does not have to correspond 13to a partition boundary, as a new block device. 14 15This is primarily useful because U-Boot's filesystem drivers only 16operate on block devices, so a block map lets you access filesystems 17wherever they might be located. 18 19The implementation is loosely modeled on Linux's "Device Mapper" 20subsystem, see `kernel documentation`_ for more information. 21 22.. _kernel documentation: https://docs.kernel.org/admin-guide/device-mapper/index.html 23 24 25Example: Netbooting an Ext4 Image 26--------------------------------- 27 28Say that our system is using an Ext4 filesystem as its rootfs, where 29the kernel is stored in ``/boot``. This image is then typically stored 30in an eMMC partition. In this configuration, we can use something like 31``load mmc 0 ${kernel_addr_r} /boot/Image`` to load the kernel image 32into the expected location, and then boot the system. No problems. 33 34Now imagine that during development, or as a recovery mechanism, we 35want to boot the same type of image by downloading it over the 36network. Getting the image to the target is easy enough: 37 38:: 39 40 dhcp ${ramdisk_addr_r} rootfs.ext4 41 42But now we are faced with a predicament: how to we extract the kernel 43image? Block maps to the rescue! 44 45We start by creating a new device: 46 47:: 48 49 blkmap create netboot 50 51Before setting up the mapping, we figure out the size of the 52downloaded file, in blocks: 53 54:: 55 56 setexpr fileblks ${filesize} + 0x1ff 57 setexpr fileblks ${filesize} / 0x200 58 59Then we can add a mapping to the start of our device, backed by the 60memory at `${loadaddr}`: 61 62:: 63 64 blkmap map netboot 0 ${fileblks} mem ${fileaddr} 65 66Now we can access the filesystem via the virtual device: 67 68:: 69 70 blkmap get netboot dev devnum 71 load blkmap ${devnum} ${kernel_addr_r} /boot/Image 72 73 74Example: Accessing a filesystem inside an FIT image 75--------------------------------------------------- 76 77In this example, an FIT image is stored in an eMMC partition. We would 78like to read the file ``/etc/version``, stored inside a Squashfs image 79in the FIT. Since the Squashfs image is not stored on a partition 80boundary, there is no way of accessing it via ``load mmc ...``. 81 82What we can to instead is to first figure out the offset and size of 83the filesystem: 84 85:: 86 87 mmc dev 0 88 mmc read ${loadaddr} 0 0x100 89 90 fdt addr ${loadaddr} 91 fdt get value squashaddr /images/ramdisk data-position 92 fdt get value squashsize /images/ramdisk data-size 93 94 setexpr squashblk ${squashaddr} / 0x200 95 setexpr squashsize ${squashsize} + 0x1ff 96 setexpr squashsize ${squashsize} / 0x200 97 98Then we can create a block map that maps to that slice of the full 99partition: 100 101:: 102 103 blkmap create sq 104 blkmap map sq 0 ${squashsize} linear mmc 0 ${squashblk} 105 106Now we can access the filesystem: 107 108:: 109 110 blkmap get sq dev devnum 111 load blkmap ${devnum} ${loadaddr} /etc/version 112