1.記事一覧
記事は複数回に分けて投稿します。Zynq7020SoCで動作する、PetaLinuxを使わない素のLinuxを構築します。
エッジArm Linux構築編(armv7l)
- 【Zynq7】Yoctoを使わずに素のLinuxをソースから構築する
- 【Zynq7】1.FSBL(1stStageBootLoader)の構築
- 【Zynq7】2.U-bootの構築
- 【Zynq7】3.Linuxカーネルの構築
- 【Zynq7】4.Zyboz7ボードのデバイスツリー構築
- 【Zynq7】5.RootFSのマウント(Ubuntu18.04)
- 【Zynq7】6.カーネルモジュールの配置
- 【Zynq7】番外編1.u-bootが途中で止まる問題 ←本ページ
- 【Zynq7】番外編2.MACアドレスをQSPIFlashから読み出して設定する
エッジArm Linux実践編(armv7l)
- 【Zynq7】実践1. LinuxにRTCを認識させる【I2Cデバイス】
- 【Zynq7】実践2. 温度センサをPython+Dockerで使う【I2Cデバイス】
- 【Zynq7】実践3. 組込みLinuxでコンテナ導入に苦労した話【Docker Engine編】
- 【Zynq7】実践4. LinuxでSPIを使う【液晶編1】
- 【Zynq7】実践5. ZynqPLのGPIOをLinuxで使う【液晶編2】
- 【Zynq7】実践6. PythonでSPI液晶を使う【液晶編3】
- 【Zynq7】閑話. SPI バス周波数が上がらない問題
2.u-bootが途中で停止してLinuxが起動しない問題
こちらがbootメッセージです。Linuxが起動せずコンソールが表示され待機状態になります。
83行目で環境変数をbootパーティションから読み出そうとして失敗したようです。
Loading Environment from FAT… *** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment
99行目でFDT関連のエラーが出ています。(FDTが何を指しているかわかりません)
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
この現象はなひたふ氏の本によると、手動でbootコマンドをu-bootコンソールに入力すると起動するそうです。
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環境変数を追記します。
#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の場合)
$ 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とおそらく同じです。確証はないです。
CONFIG_ENV_IS_IN_FAT=y
CONFIG_ENV_FAT_INTERFACE="mmc"
CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
続いて以下の設定を無効にします。#を頭につけてコメントアウトします。
#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パーティション)から環境をロードできないというメッセージがでます。これは先程と同じです。
MMC: mmc@e0100000: 0
Loading Environment from FAT… *** Error - No Valid Environment Area found
*** Warning - bad env area, using default environment
ここで、環境変数を表示してみます。
Zynq> printenv
bootcmd環境変数の内容がデフォルトでは”bootcmd=run distro_bootcmd”となっています。こちらを書き換えます。setenvコマンドを使用します(改行してはだめです)。
$ setenv bootcmd "fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000"
printコマンドでbootcmd環境変数を表示します。すると、bootcmdが設定どおりになるはずです。
Zynq> print bootcmd
bootcmd=fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000
4-5. u-boot環境変数の保存
環境変数を保存します。saveenvコマンドを使用すると、不揮発領域に環境変数が保存されます。間違った保存のされ方をすると、不揮発ROMが破壊されることがありますので、注意してください。
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行目は
Loading Environment from FAT... *** Warning - some problems detected reading environment; recovered successfully
問題が出たようですが、正常に解決できたそうです。詳細がわからないのでもやもやしますがとりあえず環境変数は読み込めたようなので良しとしましょう。
4-7. 懸念点:Flashには本当に何も書き込まれていないのか
今回u-bootコンソール上ではSDカードに環境変数が保存できたように思えましたが、搭載されているQSPIFlashに本当に何も書き込んでいないのかは確認できませんでした。私がboot無知過ぎるせいですね。