Beaglebone blackにLinuxソースとU-BOOTとbusyboxを使ってブートした時発生した問題の一つ。 私の場合にやった方法を上げておきます。 英語のサイト含め結構調べたのですが、なかなか見つからなかったので、busyboxを使う方の場合は参考になるかもしれません。 また公式サイトのデバッグ方法も日本語訳と私の実施した方法などと公式サイトのリンク先も載せています。
解決方法
結論は、私の場合はBusyBoxで『Build static binary』を選択してビルドすることで解決しました。 これは単に一例と思います。
どこから発生しているか
Linux Kernelのソースコードを見ると、/linux/init/main.cのkernel_init()関数ないで、4つのinitが呼ばれている。 どれか一つ成功(0)すればreturn 0となり、『No working init found』で止まらない。
if (!try_to_run_init_process("/sbin/init") || !try_to_run_init_process("/etc/init") || !try_to_run_init_process("/bin/init") || !try_to_run_init_process("/bin/sh")) return 0; panic("No working init found. Try passing init= option to kernel. " "See Linux Documentation/admin-guide/init.rst for guidance.");
私の場合、No working init foundのKernelメッセージで、/sbin/init、 /etc/init、 /bin/init、 /bin/sh全て表示されていました。 しかし、正常動作した時は/sbin/initしか表示されませんでした。 busyboxには/sbin/initと/bin/shがbusyboxにソフトリンクされています。 なので、正常動作時は/sbin/init->busyboxで動作していると思います。
公式サイトのデバッグ方法
使用しているLinux Kernelソースの./linux/Documentation/admin-guide/init.rstの中にも同じ内容が載っているが、webの方が翻訳出来るので便利。
私の問題は2のinit binary doesn’t exist on rootfsでした。
Google翻訳を修正して、補足をつけたのを貼り付けます。(2022年12月1日時点のものです)
- ルート FS をマウントできません: より詳細なカーネル メッセージを取得するには、「debug」カーネル パラメータを (ブートローダー構成ファイルまたは CONFIG_CMDLINE で) 設定します。
- これは、U-BOOTのboot.scrやuEnv.txtの場合、bootargsのオプションにdebugを追加すると、もう少し詳細なカーネルメッセージを表示するので、エラーを特定出来る可能性が上がるのです。
- init バイナリが rootfs に存在しません: 正しいルート FS タイプ (および root= カーネル パラメータが正しいパーティションを指している)、ストレージ ハードウェア (SCSI や USB など!) やファイル システム (ext3、 jffs2 など) が組み込まれています (またはモジュールとして、initrd によってプリロードされます)。
- 上記の場合は、まずbootargs(Kernel cmdline)に渡すrootで正しいパーティションを挿している事を確認すること。 私の場合は、Beaglebone blackのmicroSDのパーティション2がルートFSなので、root=/dev/mmcblk0p2 rw としています。 rwがなければ、別のエラーが出ます。
- 次に言っているのは、ルートFSが入っているパーティションのファイルシステム形式を正しくKernelに伝えているかを示しています。 私の場合は、bootargsにrootfstype=ext3で指定しています。
- しかし私の場合の問題は、sbin/init->busyboxとbin/sh->busyboxともにbusyboxにソフトリンクされていました。 build staticとしなかったので、busybox内にinitやshの実行バイナリが組み込まれず、initバイナリがない状態だったのだと思います。 そもそもソフトリンクとなっていたのが問題ですが。
- 壊れたコンソール デバイス: おそらく console= setup での競合 –> 初期コンソールが利用できません。例えば。一部のシリアル コンソールは、シリアル IRQ の問題 (割り込みベースの構成の欠落など) により信頼性が低くなります。別の console= device、例えばnetconsole=等を使用してみてください。
- busyboxの場合は、ルートFSの/devに文字型の特殊ファイルのconsoleを生成します。 しかし、既にconsoleが存在していたりしたらこのエラーになるのかもしれません。 これは分っていません。
- バイナリは存在しますが、依存関係は利用できません: /lib/ld-linux.so.2 などの初期化バイナリの必要なライブラリの依存関係が見つからないか破損しています。 readelf -d |grep NEEDED を使用して、必要なライブラリを見つけます。
- 私は、各ディレクトリでreadelf -d *を実行しチェックしました。
- バイナリを読み込めません: バイナリのアーキテクチャがハードウェアと一致していることを確認してください。例えば。 i386 と x86_64 の不一致、または ARM ハードウェアに x86 をロードしようとしています。ここで非バイナリ ファイル (シェル スクリプト?) を読み込もうとした場合は、スクリプトのシバン ヘッダー行 (#!/…) で完全に機能する (ライブラリの依存関係を含む) インタープリターが指定されていることを確認する必要があります。 .また、スクリプトに取り組む前に、まず /bin/sh などの単純な非スクリプト バイナリをテストし、正常に実行されることを確認してください。詳細を確認するには、init/main.c にコードを追加して、kernel_execve() の戻り値を表示します。
- 上記のmain.cのtry_to_run_init_process()の返り値はreturn kernel_execve()となっているので、initが実行された時に、このkernel_execveが何を返しているのか、何故そうなっているのかを追跡するとエラーの根源を突き止めることが出来るかもしれません。
常に更新したいとの意向が書かれているので、頻繁に更新されると思います。 なので、念の為このオリジナルサイトも確認されるのが良いと思います。
init=/etc/init.d/rcSも試してみて
エラーメッセージに『Try passing init= option to kernel』とあって、もしかしてinitの代わりのファイルを指定できると思い、rcSを全て777、nobodyにして、boot.scrのbootargsにdebug init=/etc/init.d/rcS 記述してみたけど、結果は、
- やはりinit=/etc/init.d/rcSとするとinit processとして認識してくれた。(何かの時に使える可能性あり)
- しかし実行は失敗した。 多分、/sbin/initで何か設定し、/sbin/initからrcSを呼び出さないとrcSは完全な動作にならないからだと思う。
[ 5.440288] Freeing unused kernel memory: 1024K [ 5.447436] Checked W+X mappings: passed, no W+X pages found [ 5.453236] Run /etc/init.d/rcS as init process [ 5.457823] with arguments: [ 5.460803] /etc/init.d/rcS [ 5.463976] with environment: [ 5.467148] HOME=/ [ 5.469537] TERM=linux [ 5.501296] Kernel panic - not syncing: Requested init /etc/init.d/rcS failed (error -2). [ 5.509564] ---[ end Kernel panic - not syncing: Requested init /etc/init.d/rcS failed (error -2). ]---
コメント