Linux

【Zynq7】番外編1.u-bootが途中で止まる問題

1.記事一覧

記事は複数回に分けて投稿します。Zynq7020SoCで動作する、PetaLinuxを使わない素のLinuxを構築します。

ZynqMP(arm64版)はこちら

エッジArm Linux構築編(armv7l)

エッジArm Linux実践編(armv7l)

2.u-bootが途中で停止してLinuxが起動しない問題

こちらがbootメッセージです。Linuxが起動せずコンソールが表示され待機状態になります。

83行目で環境変数をbootパーティションから読み出そうとして失敗したようです。

Bash
Loading Environment from FAT… *** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment

99行目でFDT関連のエラーが出ています。(FDTが何を指しているかわかりません)

Bash
libfdt fdt_check_header(): FDT_ERR_BADMAGIC

この現象はなひたふ氏の本によると、手動でbootコマンドをu-bootコンソールに入力すると起動するそうです。

Bash
Zynq> fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000

やってみると起動しました。ubuntuのログイン画面まで正常に出ました。

この設定をu-bootに組み込む方法は2つあるようです。

  • ubootのソースに直書きする
  • uEnv.txtに記載し、bootパーティションに配置して読み込ませる

uEnv.txtでやる方法がweb検索で多いですが、新しいu-bootはuEnv.txtが自動で読み込まれないようになっているようです。今回使用しているu-boot v2022.01 も同様で、読み込ませる方法を試行錯誤したのですが、力不足でうまくできませんでした。

その他調べるとu-bootコンソールでsetenvコマンドで環境変数を設定して、saveenvで環境変数を不揮発領域に設定する方法が見つかりました。環境変数をSDカードに保存できれば、u-bootのソースコードに直書きしなくても良さそうです。

今回は以下の2つをやってみます

  • bootコマンドをソースコードに直書きする
  • bootコマンドの環境変数を設定し、不揮発領域に保存する

3.【対策1】u-bootソースコードを改変する

まずは、ソースコードに直接bootコマンドを記述してみます。簡単ではありますが、設定を変える場合はリビルドが必要なことと、ソースの差分管理が必要になります。

git cloneしたu-bootソースの/include/configs/zynq-common.hを開きます。
“CONFIG_EXTRA_ENV_SETTINGS”のマクロ定義を探し、bootcmd環境変数を追記します。

C
#ifndef CONFIG_EXTRA_ENV_SETTINGS
#define CONFIG_EXTRA_ENV_SETTINGS \
"scriptaddr=0x20000\0" \
"script_size_f=0x40000\0" \
"fdt_addr_r=0x1f00000\0" \
"pxefile_addr_r=0x2000000\0" \
"kernel_addr_r=0x2000000\0" \
"scriptaddr=0x3000000\0" \
"ramdisk_addr_r=0x3100000\0" \
BOOTENV \
"bootcmd=fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000"
#endif

ubootを再ビルドして、mkbootしてboot.binを作り直します。

無事起動するようになりました。最後にbootログを貼っておきます。

4.【対策2】u-boot環境変数をSDカードに保存する

u-bootのコンソール上でbootcmd環境変数を設定し、SDカードに保存してみます。
再起動すると保存した環境変数を読み込んで起動してくれるはずです。この方法であれば、u-bootのソースコードを改変する必要がありません。

【警告】このやり方は環境変数を不揮発領域に保存します。意図しない保存先に保存された場合、最悪起動不可となったり、Flash、EEPROM、eMMC、SDカードなどの不揮発領域が破壊されることがあります。必ずバックアップして復旧できる環境を先に準備してください。

今回のやり方ではうまく保存できましたが、他の環境でできる保証はありません。必ずバックアップと復旧の予行練習を行いましょう。

例:rootfsのバックアップ(ホストPCがUbuntuの場合)

Bash
$ sudo rsync -av /media/user/ROOT_FS/ ~/work/backup/root_fs

4-1. u-boot defconfigの設定

defconfigで以下の設定を有効にします。mmcはSDホストインターフェース、0:1は周辺機能のSD0 or SD1のうちSD0かつパーティション1を指していると思われます。mmcblk0p1とおそらく同じです。確証はないです。

Bash
CONFIG_ENV_IS_IN_FAT=y
CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"

続いて以下の設定を無効にします。#を頭につけてコメントアウトします。

Bash
#CONFIG_ENV_IS_IN_NAND=y
#CONFIG_ENV_IS_IN_SPI_FLASH=y

4-2. ソースコード改変の取り消し

「4.【対策1】」でzynq-common.hの”CONFIG_EXTRA_ENV_SETTINGS”マクロに独自にbootcmd環境変数を追加していた場合は取り消しましょう。

4-3. リビルド

リビルドして、bootgenコマンドでboot.binを作り直します。

4-4. u-boot環境変数の設定

SDカードをセットし、起動します。以下のログのように起動せず、コンソールの入力待ちになります。

92行目でFATパーティション(第1bootパーティション)から環境をロードできないというメッセージがでます。これは先程と同じです。

Bash
MMC:   mmc@e0100000: 0
Loading Environment from FAT… *** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment

ここで、環境変数を表示してみます。

Bash
Zynq> printenv

bootcmd環境変数の内容がデフォルトでは”bootcmd=run distro_bootcmd”となっています。こちらを書き換えます。setenvコマンドを使用します(改行してはだめです)。

Bash
$ setenv bootcmd "fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000"

printコマンドでbootcmd環境変数を表示します。すると、bootcmdが設定どおりになるはずです。

Bash
Zynq> print bootcmd
bootcmd=fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000

4-5. u-boot環境変数の保存

環境変数を保存します。saveenvコマンドを使用すると、不揮発領域に環境変数が保存されます。間違った保存のされ方をすると、不揮発ROMが破壊されることがありますので、注意してください。

Bash
Zynq> saveenv
Saving Environment to FAT… OK
Zynq>

私の環境ではきちんとFATパーティションに保存されたようです。

一度電源を落としてSDカードの中身を確認します。FAT(第1boot)パーティションに

  • uboot-redund.env

が追加されていました。

4-6. u-boot-redund.envを覗いてみる

試しにこのファイルを開いてみます。バイナリファイルなので無理やりvscodeで開いてみます。


読めなくは無いですね。CRCによる改ざん防止がついているらしいので編集は厳しそうです。

SDカードを挿して起動してみます。無事起動しました。起動ログを貼っておきます。

92行目は

Bash
Loading Environment from FAT... *** Warning - some problems detected reading environment; recovered successfully

問題が出たようですが、正常に解決できたそうです。詳細がわからないのでもやもやしますがとりあえず環境変数は読み込めたようなので良しとしましょう。

4-7. 懸念点:Flashには本当に何も書き込まれていないのか

今回u-bootコンソール上ではSDカードに環境変数が保存できたように思えましたが、搭載されているQSPIFlashに本当に何も書き込んでいないのかは確認できませんでした。私がboot無知過ぎるせいですね。

ABOUT ME
sh-goto
組込エンジニア. 最近の遊びはLinuxの低レイヤいじりとXilinxのZynqとFPGAを使った電子工作
関連記事