blkmap.rst 3.2 KB

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