Quantcast
Channel: プログラミング
Viewing all articles
Browse latest Browse all 8171

QEMUで組み込みLinux(Buildroot+BusyBox+U-Boot)をinitramfsで起動する - daisukeの技術ブログ

$
0
0

前回は、QEMU で Arm の組み込み Linux(Buildroot+BusyBox)で、U-Boot を追加しました。

今回は、initramfsを追加していきます。

それでは、やっていきます。

はじめに

「QEMUを動かす」の記事一覧です。良かったら参考にしてください。

QEMUを動かすの記事一覧
・第1回:STM32(ARM Cortex-M)をQEMUで動かす(環境構築編)
・第2回:STM32(ARM Cortex-M)をQEMUで動かす(ソースコード確認編)
・第3回:STM32(ARM Cortex-M)をQEMUで動かす(スタートアップルーチン編)
・第4回:STM32(ARM Cortex-M)をQEMUで動かす(リンカスクリプト編)
・第5回:STM32(ARM Cortex-M)のELFファイルの内容を確認する
・第6回:STM32(ARM Cortex-M)のELFファイル⇔バイナリの変換を行う
・第7回:STM32(ARM Cortex-M)のバイナリから構築したELFファイルをQEMUで動かす
・第8回:QEMUのビルドに必要なxpm(xPack Project Manager)について学ぶ
・第9回:QEMUをソースからビルドして動かす
・第10回:QEMUのソースコードを変更してSTM32の動作を変える
・第11回:QEMUに似たRenodeというOSSの組込みデバイスエミュレータを試す
・第12回:QEMUに似たRenodeでSTM32をGDBを使ってデバッグする
・第13回:QEMUに似たRenodeでSTM32をバイナリファイルで動かす
・第14回:QEMUに似たRenodeをソースからビルドする
・第15回:QEMUに似たRenodeでVSCodeを使ってデバッグする
・第16回:QEMUに似たRenodeでVSCodeを使ってRenode自体をデバッグする
・第17回:QEMUで組み込みLinux(Buildroot+BusyBox)をやってみる
・第18回:QEMUで組み込みLinux(Buildroot+BusyBox)をやってみる、の補足
・第19回:QEMUで組み込みLinux(Buildroot+BusyBox)にU-Bootを追加する
・第20回:QEMUで組み込みLinux(Buildroot+BusyBox+U-Boot)で起動する
・第21回:QEMUで組み込みLinux(Buildroot+BusyBox+U-Boot)をinitramfsで起動する ← 今回

以下は、Buildroot の Documentation のリンクです。

https://buildroot.org/downloads/manual/manual.html

環境は、VirtualBox に入れた Ubuntu 22.04 です。

Buildroot の menuconfig では、qemu_arm_vexpress_defconfigを指定して、U-Boot を有効にして、U-Boot の Board defconfig に、express_ca9x4を指定しています。

今回は、initramfs を追加します。

initramfsの調査

initramfs については、kenerl のドキュメントがあります。

https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt

「What is initramfs?」を和訳してもらいます(from ChatGPT)。

initramfsとは?

すべての2.6 Linuxカーネルには、gzip圧縮された「cpio」形式のアーカイブが含まれています。カーネルが起動すると、このアーカイブはrootfsに展開(ここで言う展開とは、gzip の解凍や cpio の展開のこと)されます。展開後、カーネルはrootfs内に「init」というファイルがあるかを確認し、あればそれをPID 1として実行します。このinitプロセスはシステムを起動し、実際のルートデバイスを見つけてマウントする役割を担います(このマウントされたものが最終的なルートファイルシステム)。もしinitプログラムが見つからなければ、カーネルは従来の方法でルートパーティションを見つけ、/sbin/initの変種を実行します。

initramfsと旧initrdの違い

旧initrdは常に別ファイルであったが、initramfsアーカイブはLinuxカーネルイメージにリンクされている。 旧initrdはgzippedファイルシステムイメージ(例えばext2)であったが、新しいinitramfsアーカイブはgzipped cpioアーカイブである。 旧initrdのプログラムはカーネルに戻ることを期待されていたが、initramfsのinitプログラムはカーネルに戻ることを期待されていない。 別のルートデバイスに切り替える際、initrdはpivot_rootを使用していたが、initramfsはrootfsであるためpivot_rootもアンマウントもできない。代わりにrootfsの内容を削除し、新しいルートで上書きマウントし、新しいinitを実行する。 このプロセスは複雑なため、klibcパッケージはこれを支援するプログラム(utils/run_init.c)を導入しました。多くのパッケージ(例:busybox)はこのコマンドを「switch_root」と名付けています。

initramfs へのデータ投入

2.6 カーネル ビルド プロセスでは、常に gzip 圧縮された cpio 形式の initramfs アーカイブが作成され、結果のカーネル バイナリにリンクされます。デフォルトでは、このアーカイブは空です (x86 では 134 バイトを消費します)。

構成オプション CONFIG_INITRAMFS_SOURCE (menuconfig の General Setup にあり、usr/Kconfig にあります) を使用すると、結果のバイナリに自動的に組み込まれる initramfs アーカイブのソースを指定できます。

このオプションは、既存の gzip 圧縮された cpio アーカイブ、アーカイブするファイルを含むディレクトリ、または次の例のようなテキスト ファイル指定を指定できます。

内容が少し古いですね。

読んだ後に、丁寧な日本語訳があることを知りました。

archive.linux.or.jp

また、以下のサイトで理解が深まります。

gihyo.jp

initramfs の役割は、カーネルに組み込むカーネルモジュールを減らして、それは initramfs に持たせるということでしょうか。

今回に限って言うと、今回使っているカーネルは、単体でルートファイルシステムを展開できているので、これから initramfs を追加しよう思いますが、「無くてもいいもの」ということになります(必要ではないけど理解するために追加してみるという位置づけ)。

さらに、initramfs の実装面を解説しているサイトもありました。

qiita.com

ここを見ると、カーネルは initramfs を含んでいて、ブートローダーに渡された initramfs があれば、そちらを採用(上書きして使う)するということのようです。

追加の initramfs(ブートローダで渡される方)は、様々なデバイス(に存在するルートファイルシステム)に対応する機能追加の役割ということでしょうか。

さらに詳しいサイトがありました。

www.gcd.org

initramfs は、/init が呼ばれるようです。initramfs に BusyBox が使われるのは特別なことではないようです。

また、他に分かったことがあったら、ここに追記しようと思います。

initramfsの構築

今回も参考にさせて頂くサイトです。

leavatail.hatenablog.com

BusyBox で作れるんですね。では、やっていきます。

BusyBox の公式サイトです。

busybox.net

参考サイトでは 1_32_stable を使われていますが、現在は 1_36_stable が最新です。

Deployment の Source Control を見ます。

Git のクローン方法、チェックアウト方法が書かれています。このチェックアウト方法は補完が効かないんですよね、なんででしょうね、ということで、ここでは補完が効く方法でチェックアウトしてます。

$ git clone git://busybox.net/busybox.git
$ cd busybox/
$ git checkout 1_36_stable
Branch '1_36_stable'set up to track remote branch '1_36_stable' from 'origin'.
Switched to a new branch '1_36_stable'

公式サイトには、明確なビルド手順のページが無く、FAQ にビルド方法が書かれています。

「How do I build Busybox with a cross-compiler?」を見ると、ARCH が使われてないのかと思いましたが、ARCH でページ内検索すると、ARCH=arm をしてるところがあったので、必要そうです。

では、デフォルトのコンフィグを適用します。

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig

続いて、menuconfig でスタティックリンクの設定を行います。

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig

static で検索すると、以下のように出ます。デフォルトは static ではないようです。

Symbol: STATIC [=n]
Prompt: Build static binary (no shared libs)
  Defined at Config.in:362
  Location:
    -> Settings

チェック(*)を付けて Exit すると .config が更新されます。

では、ビルドします。

$ make -j$(nproc)ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
(省略)
  AR      util-linux/lib.a
  LINK    busybox_unstripped
Static linking against glibc, can't use --gc-sectionsTrying libraries: m resolv rt Library m is needed, can't exclude it (yet)
 Library resolv is needed, can't exclude it (yet) Library rt is not needed, excluding it Library m is needed, can't exclude it (yet)
 Library resolv is needed, can't exclude it (yet)Final link with: m resolv

最後のメッセージを見ると、エラーが出たのかと思いましたが、正常終了のようです。

$ echo$?0

make install について、公式サイトを見ましたが、明確には書かれないようです。

FAQ の「I am observing a bug in BusyBox on an obscure platform. Help.」の手順に make install が含まれている程度でしょうか。

まぁ、やってみます。

$ make -j$(nproc)ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install
  ./_install//bin/arch -> busybox
  ./_install//bin/ash -> busybox
(省略)
--------------------------------------------------
You will probably need to make your busybox binary
setuid root to ensure all configured applets will
work properly.
--------------------------------------------------

「設定されたすべてのアプレットが適切に動作することを保証するには、busybox バイナリを setuid root にする必要がある可能性があります。」という注意書きがありました。

_install に作られたようですので、見てみます。

$ cd _install/
$ tree
.
|-- bin
|   |-- arch -> busybox
|   |-- ash -> busybox
|   |-- base32 -> busybox
|   |-- base64 -> busybox
(省略)

$ tree -d
.
|-- bin
|-- sbin
`-- usr|-- bin    `-- sbin

5 directories

それらしい感じに出来てます。

init スクリプトを探します。

$ find . -name *init*
./sbin/run-init
./sbin/init
$ ll sbin/init
lrwxrwxrwx 1 daisuke daisuke 1476 19:05 sbin/init -> ../bin/busybox*

BusyBox に /sbin/init が用意されているようです。

参考サイトでは、_install 直下に init というスクリプトを用意しているようです(つまり、/init となるはず)。

先ほど見た Qiita の参考サイトでは、カーネルは、/sbin/init、/etc/init、/bin/init、/bin/sh の順に init スクリプトを探す、と書かれていたと思います(さらに調べたところ、/init で正しいようです)。

分からなくなったので、動かしながら確認していこうと思います。

とりあえず、init スクリプトは作らず、このまま initramfs を作ります。

$ find . | cpio -o--format=newc > ../rootfs.img

BusyBox のトップに rootfs.img が生成されました。

では、動かしていきます。

これまでのおさらい

Buildroot のトップディレクトリから output/images に移動したディレクトリで実行するとします。

$ cd output/images
$ ls
rootfs.ext2  start-qemu.sh  u-boot.bin  vexpress-v2p-ca9.dtb  zImage

Buildroot+BusyBoxのみ(U-Boot無し)

実際は1行で入力してますが、見にくいので、ここでは改行を入れています。

$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-drivefile=rootfs.ext2,if=sd,format=raw \-append"console=ttyAMA0,115200 rootwait root=/dev/mmcblk0"\-net nic,model=lan9118 -net user \-serial stdio

Buildroot+BusyBox+U-Boot

こちらも実際は1行で入力しています。U-Boot の autoboot を何らかのキーを押して止めて、=>の行を入力します。

$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel ../build/uboot-2024.01/u-boot \-device loader,file=zImage,addr=0x62000000 \-device loader,file=vexpress-v2p-ca9.dtb,addr=0x63000000 \-drivefile=rootfs.ext2,if=sd,format=raw \-net nic,model=lan9118 -net user \-serial stdio
=> setenv bootargs console=ttyAMA0,115200 rootwait root=/dev/mmcblk0
=> bootz  0x62000000 - 0x63000000

Buildroot+BusyBoxのみ(U-Boot無し)にinitramfsを追加する

Buildroot のトップディレクトリ/output/images に、initramfs のイメージの rootfs.img をコピーしておきます。

まずは、U-Boot 無しの環境で動かします。

-initrd rootfs.img を追加しただけです。

$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs.img \-drivefile=rootfs.ext2,if=sd,format=raw \-append"console=ttyAMA0,115200 rootwait root=/dev/mmcblk0"\-net nic,model=lan9118 -net user \-serial stdio

普通に Buildroot が起動してしまいました。起動ログを確認してみます。

initramfs を追加する前と、追加した後の差分は以下です。

+Unpacking initramfs...
 hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
 workingset: timestamp_bits=30 max_order=16 bucket_order=0
 squashfs: version 4.0 (2009/01/31) Phillip Lougher
 jffs2: version 2.2. (NAND) c 2001-2006 Red Hat, Inc.
 9p: Installing v9fs 9p2000 file system support
 io scheduler mq-deadline registered
 io scheduler kyber registered
 OF: graph: no port node found in /bus@40000000/motherboard-bus@40000000/iofpga@7,00000000/i2c@16000/dvi-transmitter@60
 sii902x 0-0060: supply iovcc not found, using dummy regulator
 sii902x 0-0060: supply cvcc12 not found, using dummy regulator
+Freeing initrd memory: 2132K

initramfs が動いてるようなログは出ています。

参考サイトをよく見ると、-append に root=/dev/mmcblk0 の指定が削除されていました。これが想定した動きと異なる原因のようです。

これを削除して、もう一度やってみます。

$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs.img \-drivefile=rootfs.ext2,if=sd,format=raw \-append"console=ttyAMA0,115200 rootwait"\-net nic,model=lan9118 -net user \-serial stdio
(省略)
input: ImExPS/2 Generic Explorer Mouse as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10007000.kmi/serio1/input/input2
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1(core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
Waiting for root device ...

起動せず、止まってしまいました。initramfs に /init のスクリプトが無いためのようです。

では、initramfs に最低限の /init を準備して、動作を確認してみます。

BusyBox の _install 直下に init というファイルを作ります。

「Hello, initramfs」と表示して、1秒ごとに日時を表示し続けるだけです。

#!/bin/shecho Hello, initramfswhile truedosleep1
  date
done

では、先ほどと同じように、rootfs.img として固めます。

$ find . | cpio -o--format=newc > ../rootfs.img

Buildroot の output/images に移動します。コピーは面倒なので、シンボリックリンクを貼っておきます。

$ cd buildroot-2024.02.3/output/images/
$ ln -s ../../../busybox/rootfs.img
$ ../host/bin/qemu-system-arm -M vexpress-a9
-smp 1-m256-kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd rootfs.img -drivefile=rootfs.ext2,if=sd,format=raw -append"console=ttyAMA0,115200 rootwait"-net nic,model=lan9118 -net user -serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /init as init process
Failed to execute /init (error -13)
Run /sbin/init as init process
can't run '/etc/init.d/rcS': No such file or directorycan't open /dev/tty2: No such file or directory
can't open /dev/tty4: No such file or directorycan't open /dev/tty3: No such file or directory
can't open /dev/tty2: No such file or directorycan't open /dev/tty4: No such file or directory
can't open /dev/tty3: No such file or directorycan't open /dev/tty2: No such file or directory

うまくいきませんでした。「Hello, initramfs」が表示されませんでした。

/init は実行されたようなのですが、うーん、少し調べてみます。

作成した /init スクリプトに実行権限を付けてなかったことが原因でした。

$ chmod+x ./init
$ find . | cpio -o--format=newc > ../rootfs.img
$ cd -
$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256-kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd rootfs.img -drivefile=rootfs.ext2,if=sd,format=raw -append"console=ttyAMA0,115200 rootwait"-net nic,model=lan9118 -net user -serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /init as init process
Hello, initramfs
Sun Jul  7 11:00:38 UTC 2024
Sun Jul  7 11:00:39 UTC 2024
Sun Jul  7 11:00:40 UTC 2024
Sun Jul  7 11:00:41 UTC 2024(省略)

想定した通りに動いています。

次は、カーネルのブートパラメータの rdinit で、initramfs の /init 以外を実行するようにしてみます。

具体的には、-append に「rdinit=/bin/sh」を追加して、/bin/sh(シェル)を起動してみます。

$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs.img \-drivefile=rootfs.ext2,if=sd,format=raw \-append"console=ttyAMA0,115200 rootwait rdinit=/bin/sh"\-net nic,model=lan9118 -net user \-serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /bin/sh as init process
/bin/sh: can't access tty; job control turned off~ # lsbin      dev      init     linuxrc  root     sbin     usr# ls /dev/console

うまくいきました。

次は、Buildroot(ルートファイルシステム)を起動してみます。

参考サイトによると、/dev、/proc、/sys を作り、Buildroot をマウントし、/dev、/proc、/sys を Buildroot に移動し、switch_root を実行しているようです。

最小限から試してみます。本来なら、/dev/mmcblk0 を適当なディレクトリにマウントし、そこに switch_root する必要があるようですが、もしかしたら出来るかな、と思って試します。

initramfs の /init を以下のようにしました。

#!/bin/shecho Hello, initramfsexec switch_root -c /dev/console /dev/mmcblk0 /sbin/init

-append の「rdinit=/bin/sh」は削除します。

$ find . | cpio -o--format=newc > ../rootfs.img
$ cd -
$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs.img \-drivefile=rootfs.ext2,if=sd,format=raw \-append"console=ttyAMA0,115200 rootwait"\-net nic,model=lan9118 -net user \-serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /init as init process
Hello, initramfs
switch_root: can't change directory to '/dev/mmcblk0': No such file or directoryKernel panic - not syncing: Attempted to kill init! exitcode=0x00000100CPU: 0 PID: 1 Comm: switch_root Not tainted 6.1.44 #1Hardware name: ARM-Versatile Express unwind_backtrace from show_stack+0x10/0x14 show_stack from dump_stack_lvl+0x40/0x4c dump_stack_lvl from panic+0x108/0x318 panic from make_task_dead+0x0/0x17c---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100 ]---

さすがにダメでした。では、initramfs の /init を以下のように書き換えます。

#!/bin/shecho Hello, initramfs

mount /dev/mmcblk0 /mnt/newroot
exec switch_root -c /dev/console /mnt/newroot /sbin/init

BusyBox の _install に /mnt/newroot というディレクトリを作っておきます。

$ mkdir-p mnt/newroot
$ find . | cpio -o--format=newc > ../rootfs.img
$ cd -
$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256-kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd rootfs.img -drivefile=rootfs.ext2,if=sd,format=raw -append"console=ttyAMA0,115200 rootwait"-net nic,model=lan9118 -net user -serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /init as init process
Hello, initramfs
mount: mounting /dev/mmcblk0 on /mnt/newroot failed: No such file or directory
BusyBox v1.36.1(2024-07-06 18:36:47 JST) multi-call binary.

Usage: switch_root [-c CONSOLE_DEV] NEW_ROOT NEW_INIT [ARGS]

Free initramfs and switch to another root fs:
chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,
execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.

        -c DEV  Reopen stdio to DEV after switch
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100
CPU: 0 PID: 1 Comm: switch_root Not tainted 6.1.44#1
Hardware name: ARM-Versatile Express
 unwind_backtrace from show_stack+0x10/0x14
 show_stack from dump_stack_lvl+0x40/0x4c
 dump_stack_lvl from panic+0x108/0x318
 panic from make_task_dead+0x0/0x17c
---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100]---

ダメでした。やはり、/dev/mmcblk0 が見つからないということでしょうか。

シェルに戻して、手動でやってみます。

$ ../host/bin/qemu-system-arm -M vexpress-a9 -smp1-m256\-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs.img \-drivefile=rootfs.ext2,if=sd,format=raw \-append"console=ttyAMA0,115200 rootwait rdinit=/bin/sh"\-net nic,model=lan9118 -net user \-serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /bin/sh as init process
/bin/sh: can't access tty; job control turned off~ # lsbin      dev      init     linuxrc  mnt      root     sbin     usr~ # mount -t devtmpfs devtempfs /dev~ # ls /devconsole          ptype            tty34            tty8cpu_dma_latency  ptypf            tty35            tty9full             random           tty36            ttyAMA0gpiochip0        rtc0             tty37            ttyAMA1gpiochip1        snd              tty38            ttyAMA2gpiochip2        tty              tty39            ttyAMA3gpiochip3        tty0             tty4             ttyp0hwrng            tty1             tty40            ttyp1input            tty10            tty41            ttyp2kmsg             tty11            tty42            ttyp3mem              tty12            tty43            ttyp4mmcblk0          tty13            tty44            ttyp5mtd0             tty14            tty45            ttyp6mtd0ro           tty15            tty46            ttyp7mtd1             tty16            tty47            ttyp8mtd1ro           tty17            tty48            ttyp9mtdblock0        tty18            tty49            ttypamtdblock1        tty19            tty5             ttypbnull             tty2             tty50            ttypcptmx             tty20            tty51            ttypdptyp0            tty21            tty52            ttypeptyp1            tty22            tty53            ttypfptyp2            tty23            tty54            ubi_ctrlptyp3            tty24            tty55            urandomptyp4            tty25            tty56            usbmon0ptyp5            tty26            tty57            vcsptyp6            tty27            tty58            vcs1ptyp7            tty28            tty59            vcsaptyp8            tty29            tty6             vcsa1ptyp9            tty3             tty60            vcsuptypa            tty30            tty61            vcsu1ptypb            tty31            tty62            zeroptypc            tty32            tty63ptypd            tty33            tty7~ # mount /dev/mmcblk0 /mnt/newrootmount: mounting /dev/mmcblk0 on /mnt/newroot failed: No such file or directory~ # ls /dev/mmcblk0/dev/mmcblk0~ # ls /mnt/newroot~ # mount -t ext4 /dev/mmcblk0 /mnt/newrootEXT4-fs (mmcblk0): warning: mounting unchecked fs, running e2fsck is recommendedEXT4-fs (mmcblk0): mounted filesystem without journal. Quota mode: disabled.~ # ls /mnt/newroot/bin         lib         lost+found  opt         run         tmpdev         lib32       media       proc        sbin        usretc         linuxrc     mnt         root        sys         var~ # umount /mnt/newroot/EXT4-fs (mmcblk0): unmounting filesystem.~ # ls /mnt/newroot/~ # mount -t ext2 /dev/mmcblk0 /mnt/newrootEXT2-fs (mmcblk0): warning: mounting unchecked fs, running e2fsck is recommendedext2 filesystem being mounted at /mnt/newroot supports timestamps until 2038 (0x7fffffff)~ # ls /mnt/newroot/bin         lib         lost+found  opt         run         tmpdev         lib32       media       proc        sbin        usretc         linuxrc     mnt         root        sys         var

なぜマウントできないのかな、と思ったら、まず、/dev を devtmpfs としてマウントが必要だったようです。

また、ルートファイルシステムのマウントには、-t の指定が必要なようです。

あと、ext2 なのか、ext4 なのかは、これだけでは判断できません。まずは、ext2 でやってみたいと思います。

では、initramfs の /init を書き換えます。

#!/bin/shecho Hello, initramfs

mount -t devtmpfs devtempfs /dev
mount -t ext2 /dev/mmcblk0 /mnt/newroot
exec switch_root -c /dev/console /mnt/newroot /sbin/init

では、やってみます。

$ find . | cpio -o--format=newc > ../rootfs.img
$ cd -
$ ../host/bin/qemu-system-arm -M vexpress-a9
-smp 1-m256-kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd rootfs.img -drivefile=rootfs.ext2,if=sd,format=raw -append"console=ttyAMA0,115200 rootwait"-net nic,model=lan9118 -net user -serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /init as init process
Hello, initramfs
EXT2-fs (mmcblk0): warning: mounting unchecked fs, running e2fsck is recommended
ext2 filesystem being mounted at /mnt/newroot supports timestamps until 2038(0x7fffffff)switch_root: can't open '/dev/console': No such file or directorycan't open /dev/null: No such file or directorycan't open /dev/null: No such file or directorycan't open /dev/null: No such file or directorycan't open /dev/null: No such file or directorycan't open /dev/ttyAMA0: No such file or directorycan't open /dev/ttyAMA0: No such file or directorycan't open /dev/ttyAMA0: No such file or directorycan't open /dev/ttyAMA0: No such file or directorycan't open /dev/ttyAMA0: No such file or directory

/dev を新しいルートに移動してないことが原因のようです。

initramfs の /init に追加します。

#!/bin/shecho Hello, initramfs

mount -t devtmpfs devtempfs /dev
mount -t ext2 /dev/mmcblk0 /mnt/newroot
mount -n-o move /dev /mnt/newroot/dev
exec switch_root -c /dev/console /mnt/newroot /sbin/init

では、やってみます。

$ find . | cpio -o--format=newc > ../rootfs.img
$ cd -
$ ../host/bin/qemu-system-arm -M vexpress-a9
-smp 1-m256-kernel zImage -dtb vexpress-v2p-ca9.dtb -initrd rootfs.img -drivefile=rootfs.ext2,if=sd,format=raw -append"console=ttyAMA0,115200 rootwait"-net nic,model=lan9118 -net user -serial stdio
(省略)
Freeing unused kernel image (initmem) memory: 1024K
Run /init as init process
Hello, initramfs
EXT2-fs (mmcblk0): warning: mounting unchecked fs, running e2fsck is recommended
ext2 filesystem being mounted at /mnt/newroot supports timestamps until 2038(0x7fffffff)(省略)Welcome to Buildrootbuildroot login: root# ls -aF /proc/./             25/            45/            device-tree@   mtd../            26/            46/            devices        net@1/             27/            47/            diskstats      pagetypeinfo10/            28/            5/             driver/        partitions11/            29/            51/            execdomains    self@117/           3/             52/            fb             slabinfo119/           30/            6/             filesystems    softirqs12/            31/            7/             fs/            stat124/           32/            73/            interrupts     swaps13/            33/            77/            iomem          sys/14/            34/            8/             ioports        sysrq-trigger15/            35/            9/             irq/           sysvipc/16/            36/            asound/        kallsyms       thread-self@17/            37/            buddyinfo      kmsg           timer_list18/            38/            bus/           kpagecount     tty/19/            39/            cgroups        kpageflags     uptime2/             4/             cmdline        loadavg        version20/            40/            config.gz      locks          vmallocinfo21/            41/            consoles       meminfo        vmstat22/            42/            cpu/           misc           zoneinfo23/            43/            cpuinfo        modules24/            44/            crypto         mounts@# ls -aF /sys/./        block/    class/    devices/  fs/       module/../       bus/      dev/      firmware/ kernel/   power/

無事に、Buildroot が起動しました。特にエラーは見当たりません。

initramfs の /init に、/proc と /sys を追加せずにやりましたが、特に問題なさそうです。

initramfs で、/proc と /sys を使う場合は必要ということだと思います。

最小限の構成で失敗しながら追加していくことで、理解が深まりました。

おわりに

今回は、initramfs についての調査と、実際に BusyBox を使って initramfs を作って動作させてみました。

BusyBox のロゴを探してみたところ、段ボール箱の画像のようです。ありがたく使わせて頂きます。

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。


Viewing all articles
Browse latest Browse all 8171

Trending Articles