前回は、QEMU で Arm の組み込み Linux(Buildroot+BusyBox)で、U-Boot を追加しました。
今回は、initramfsを追加していきます。
それでは、やっていきます。
はじめに
「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 アーカイブ、アーカイブするファイルを含むディレクトリ、または次の例のようなテキスト ファイル指定を指定できます。
内容が少し古いですね。
読んだ後に、丁寧な日本語訳があることを知りました。
また、以下のサイトで理解が深まります。
initramfs の役割は、カーネルに組み込むカーネルモジュールを減らして、それは initramfs に持たせるということでしょうか。
今回に限って言うと、今回使っているカーネルは、単体でルートファイルシステムを展開できているので、これから initramfs を追加しよう思いますが、「無くてもいいもの」ということになります(必要ではないけど理解するために追加してみるという位置づけ)。
さらに、initramfs の実装面を解説しているサイトもありました。
ここを見ると、カーネルは initramfs を含んでいて、ブートローダーに渡された initramfs があれば、そちらを採用(上書きして使う)するということのようです。
追加の initramfs(ブートローダで渡される方)は、様々なデバイス(に存在するルートファイルシステム)に対応する機能追加の役割ということでしょうか。
さらに詳しいサイトがありました。
initramfs は、/init が呼ばれるようです。initramfs に BusyBox が使われるのは特別なことではないようです。
また、他に分かったことがあったら、ここに追記しようと思います。
initramfsの構築
今回も参考にさせて頂くサイトです。
BusyBox で作れるんですね。では、やっていきます。
BusyBox の公式サイトです。
参考サイトでは 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 147月 6 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 のロゴを探してみたところ、段ボール箱の画像のようです。ありがたく使わせて頂きます。
最後になりましたが、エンジニアグループのランキングに参加中です。
気楽にポチッとよろしくお願いいたします🙇
今回は以上です!
最後までお読みいただき、ありがとうございました。