blob: dbfa8e5aad7c7ed8c595b76ec6a22f1f392255f2 [file] [log] [blame]
Tobias Waldekranz135d1472023-02-16 16:33:54 +01001.. 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