mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-30 08:07:59 +00:00
doc: blkmap: Add introduction and examples
Explain block maps by going through two common use-cases. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
6da06a0338
commit
3eee5d073a
3 changed files with 113 additions and 0 deletions
|
@ -797,6 +797,7 @@ BLKMAP
|
||||||
M: Tobias Waldekranz <tobias@waldekranz.com>
|
M: Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: cmd/blkmap.c
|
F: cmd/blkmap.c
|
||||||
|
F: doc/usage/blkmap.rst
|
||||||
F: drivers/block/blkmap.c
|
F: drivers/block/blkmap.c
|
||||||
F: include/blkmap.h
|
F: include/blkmap.h
|
||||||
F: test/dm/blkmap.c
|
F: test/dm/blkmap.c
|
||||||
|
|
111
doc/usage/blkmap.rst
Normal file
111
doc/usage/blkmap.rst
Normal file
|
@ -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
|
|
@ -4,6 +4,7 @@ Use U-Boot
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
blkmap
|
||||||
dfu
|
dfu
|
||||||
environment
|
environment
|
||||||
fdt_overlays
|
fdt_overlays
|
||||||
|
|
Loading…
Add table
Reference in a new issue