みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

YoctoProject u-bootのextlinux.confを使う

はじめに

ブートローダにu-bootを使用する場合、カーネルやデバイスツリーを指定するためにextlinux.confを使用することができる。 このファイルをu-bootが見つけると、そこに記述されているカーネルやデバイスツリーを読み込むようになる。 u-bootのコンソールで環境変数を変更したりせずに、カーネルやデバイスツリーを差し替えることができるため便利。

通常であればこの手のファイルをシステムに組み込む場合、レシピでファイルを追加する必要があるが、 local.confなどで変数を設定することでこのファイルを生成させることができる。

ターゲットはリファレンスボードの1つであるBeagleBone Blackを使用する。

extlinux.conf

設定方法

local.confやu-bootのレシピで下記のように設定する。

MACHINE ?= "beaglebone-yocto"

UBOOT_EXTLINUX = "1"
UBOOT_EXTLINUX_KERNEL_IMAGE = "/zImage"
UBOOT_EXTLINUX_FDT = "/am335x-boneblack.dtb"
UBOOT_EXTLINUX_ROOT = "root=/dev/mmcblk0p2"
IMAGE_BOOT_FILES:append = " \
    extlinux.conf;extlinux/extlinux.conf \
"

この設定でイメージを作成し、実機上で/boot/extlinux/extlinux.confの内容を確認する。

# Generic Distro Configuration file generated by OpenEmbedded
LABEL Poky (Yocto Project Reference Distro)
        KERNEL /zImage
        FDT /am335x-boneblack.dtb
        APPEND root=/dev/mmcblk0p2 rootwait rw console=${console},${baudrate}

この様に設定が反映されていることがわかる。

関連する変数

この処理はuboot-extlinux-config.bbclassによって行われる。

このファイルのヘッダコメントを見ると下記の変数で内容を制御できることがわかる。

# External variables:
#
# UBOOT_EXTLINUX_CONSOLE           - Set to "console=ttyX" to change kernel boot
#                                    default console.
# UBOOT_EXTLINUX_LABELS            - A list of targets for the automatic config.
# UBOOT_EXTLINUX_KERNEL_ARGS       - Add additional kernel arguments.
# UBOOT_EXTLINUX_KERNEL_IMAGE      - Kernel image name.
# UBOOT_EXTLINUX_FDTDIR            - Device tree directory.
# UBOOT_EXTLINUX_FDT               - Device tree file.
# UBOOT_EXTLINUX_INITRD            - Indicates a list of filesystem images to
#                                    concatenate and use as an initrd (optional).
# UBOOT_EXTLINUX_MENU_DESCRIPTION  - Name to use as description.
# UBOOT_EXTLINUX_ROOT              - Root kernel cmdline.
# UBOOT_EXTLINUX_TIMEOUT           - Timeout before DEFAULT selection is made.
#                                    Measured in 1/10 of a second.
# UBOOT_EXTLINUX_DEFAULT_LABEL     - Target to be selected by default after
#                                    the timeout period

uboot-extlinux-config.bbclassはu-bootのレシピからinheritされるため、明示的にinheritを追加する必要は無い。

initramfsを追加する

initramfsをカーネルにバンドルしない状態で、使用できるようにしてみる。

local.confを下記のようにする。

MACHINE ?= "beaglebone-yocto"

INITRAMFS_IMAGE = "core-image-minimal-initramfs"
INITRAMFS_FSTYPES = "cpio"
IMAGE_FSTYPES_pn-${INITRAMFS_IMAGE} = "${INITRAMFS_FSTYPES}"

INITRAMFS_SCRIPTS = "\
                      initramfs-framework-base \
                      initramfs-module-debug \
 "

UBOOT_EXTLINUX = "1"
UBOOT_EXTLINUX_KERNEL_IMAGE = "/zImage"
UBOOT_EXTLINUX_FDT = "/am335x-boneblack.dtb"
UBOOT_EXTLINUX_INITRD = "/initramfs"
UBOOT_EXTLINUX_ROOT = "root=/dev/mmcblk0p2"
UBOOT_EXTLINUX_KERNEL_ARGS:append = " debug"
IMAGE_BOOT_FILES:append = " \
    extlinux.conf;extlinux/extlinux.conf \
    ${INITRAMFS_IMAGE}-${MACHINE}.cpio;initramfs \
"

initramfsが実行されていることを確認できるように変えるパラメータにdebugを追加している。

これでイメージを作成し、実機で起動する。

...(snip)...
DEBUG: Loading module debug
DEBUG: Running debug_run
DEBUG: Calling module hook (post): debug_hook_handler
DEBUG: Finished module hook (post): debug_hook_handler
DEBUG: Loading module rootfs
DEBUG: Calling module hook (pre): debug_hook_handler
DEBUG: Finished module hook (pre): debug_hook_handler
DEBUG: Running rootfs_run
DEBUG: No e2fs compatible filesystem has been mounted, mounting /dev/mmcblk0p2...
EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null). Quota mode: disabled.
DEBUG: Calling module hook (post): debug_hook_handler
DEBUG: Finished module hook (post): debug_hook_handler
DEBUG: Loading module finish
DEBUG: Calling module hook (pre): debug_hook_handler
DEBUG: Finished module hook (pre): debug_hook_handler
DEBUG: Running finish_run
DEBUG: Moving basic mounts onto rootfs
DEBUG: Moving /dev, /proc and /sys onto rootfs...
...(snip)...

作成されたextlinux.confは下記のようになっている。

# Generic Distro Configuration file generated by OpenEmbedded
LABEL Poky (Yocto Project Reference Distro)
        KERNEL /zImage
        FDT /am335x-boneblack.dtb
        INITRD /initramfs
        APPEND root=/dev/mmcblk0p2 rootwait rw debug console=${console},${baudrate}

UBOOT_EXTLINUXを無効化しても消えない場合

extlinux.confを使用しなくても良い場合や使用したくない場合は、UBOOT_EXTLINUXに0を明示するか、 そもそも関連する変数をしなければ、extlinux.confは生成されなくなるはず。 しかし、beaglebone-yoctoでは、これらを無効化してもデフォルト設定で何故かextlinux.confが作成されてしまう。

extlinux.confを追加しているレシピがいるのか調べたがそれも見つからない。 調査した結果wicコマンドが自動的に作成されていることがわかった。

poky/scripts/lib/wic/plugins/source/bootimg-partition.pyがその処理を行っている。

class BootimgPartitionPlugin(SourcePlugin):
...(snip)...
    name = 'bootimg-partition'

    @classmethod
    def do_configure_partition(cls, part, source_params, cr, cr_workdir,
                             oe_builddir, bootimg_dir, kernel_dir,
                             native_sysroot):
...(snip)...
        if source_params.get('loader') != "u-boot":
            return
...(snip)...
        install_cmd = "install -d %s/extlinux/" % hdddir
        exec_cmd(install_cmd)
        cfg = open("%s/extlinux/extlinux.conf" % hdddir, "w")
        cfg.write(extlinux_conf)
        cfg.close()

wksファイルの中でsourceプラグインにbootimg-partitionを設定している場合このクラスの処理が実行される。 do_configure_partitionクラスメソッドでextlinux.confを作成していることがわかった。 作成処理の前に下記の条件で処理を抜けている。loaderの指定がu-bootになっている場合処理が継続されるため、 extlinux.confが作成されてしまう。

        if source_params.get('loader') != "u-boot":
            return

u-bootを使用している場合は常にextlinux.confは作成されるのだろうか? ARM系のu-bootを使用するSBCでwicイメージを作成しているが、逆にextlinux.confを見かけることのほうが珍しい気がする。

コードを調べていった結果、source_paramsの内容はwksの--sourceparamsオプションによって設定されることがわかった。 beaglebone-yoctoのwksであるpoky/meta-yocto-bsp/wic/beaglebone-yocto.wksを確認する。

# short-description: Create SD card image for Beaglebone
# long-description: Creates a partitioned SD card image for Beaglebone.
# Boot files are located in the first vfat partition.

part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4 --fixed-size 32 --sourceparams="loader=u-boot" --use-uuid
part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --label root --align 4 --use-uuid
bootloader --append="console=ttyS0,115200"

/bootの行で--sourceparams="loader=u-boot"と記述がある。これが原因でextlinux.confが強制的に作成されているということがわかった。

UBOOT_EXTLINUX関連を削除したlocal.confでbitbakeを実行したあとで、 次のようにbeaglebone-yocto-wo-extlinux.wksを作成し、wicイメージを作成してみる。

part /boot --source bootimg-partition --ondisk mmcblk0 --fstype=vfat --label boot --active --align 4 --fixed-size 32 --use-uuid
part / --source rootfs --ondisk mmcblk0 --fstype=ext4 --label root --align 4 --use-uuid
bootloader --append="console=ttyS0,115200"

wicの挙動がわかりやすいようにbitbakeではなくwicコマンドでイメージを作成する。

$ wic create -e core-image-minimal --debug -o output beaglebone-yocto-wo-extlinux.wks

output/beaglebone-yocto-wo-extlinux-202304201044-mmcblk0.directが作成されたwicイメージとなる。ファイル名に日時が含まれているため、実際に作業した環境によってファイル名は変化する。

第1パーティションを確認する。

$ wic ls output/beaglebone-yocto-wo-extlinux-202304201044-mmcblk0.direct:1
Volume in drive : is boot       
 Volume Serial Number is 9E47-A953
Directory for ::/

MLO             107932 2023-04-20   1:47 
AM335X~1 DTB     63701 2023-04-20   1:47  am335x-bone.dtb
AM335X~2 DTB     67151 2023-04-20   1:47  am335x-boneblack.dtb
AM335X~3 DTB     63965 2023-04-20   1:47  am335x-bonegreen.dtb
u-boot   img   1224900 2023-04-20   1:47 
ZIMAGE         7849952 2023-04-20   1:47  zImage
        6 files           9 377 601 bytes
                         24 086 528 bytes free

extlinuxディレクトリとextlinux.confが存在しないことが確認できた。

--sourceparams="loader=u-boot"はwicでデフォルト設定のextlinux.confを作成するためのフラグとして作用するので、 単にextlinux.confが欲しい場合はこの設定は不要で、local.confなどでUBOOT_EXTLINUX関連の変数を設定するだけ良い。

まとめ

  • u-bootでextlinux.confを使用するといろいろ便利
  • YoctoProjectではUBOOT_EXTLINUXの変数設定でこのファイルを自動作成できる
  • extlinux.confが不要なのになぜか作成される場合はwksの--sourceparams="loader=u-boot"を疑ってみる