UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(U-Boot編)


## はじめに

UltraZed-EG スターターキットに Debian GNU/Linux (v2018.2版) を構築する方法について、具体的な方法をいくつかに分けて説明します。

 * [Introduction](https://qiita.com/ikwzm/items/5b657ebd8895945c4eae)
 * [Boot Loader](https://qiita.com/ikwzm/items/a0dfef6355cf839ebc08)
   - [Sample FPGA Design](https://qiita.com/ikwzm/items/aae6e17e7d08b089e010)
   - [FSBL   (First Stage Boot Loader)](https://qiita.com/ikwzm/items/a94c79d78b89fc2e31f8)
   - [PMUFW  (Platform Manager Unit Firmware)](https://qiita.com/ikwzm/items/06aeaa22e9b25d21ef88)
   - [BL31   (ARM Trusted Firmware Boot Loader state 3-1)](https://qiita.com/ikwzm/items/4735be0fbdd1e51c7c59)
   - __U-Boot(この記事)__
   - [BOOT.BIN](https://qiita.com/ikwzm/items/d0482bf8bfc7912ff746)
 * [Linux Kernel](https://qiita.com/ikwzm/items/d5417b39c983f8e56af9)
 * [Debian9 Root File System](https://qiita.com/ikwzm/items/a0e88798ed29b30fa003)

この記事では、ZynqMP の Boot Loader で使うための U-Boot の構築について説明をします。

## u-boot の構築

### 必要な環境

* gcc-aarch64-linux-gnu

### Boot Loader 構築環境の準備

次の URL から git clone でリポジトリをダウンロードして v2018.2.0 をチェックアウトします。

 * [https://github.com/ikwzm/ZynqMP-FPGA-Linux](https://github.com/ikwzm/ZynqMP-FPGA-Linux)

```console
shell$ git clone git://github.com/ikwzm/ZynqMP-FPGA-Linux
shell$ cd ZynqMP-FPGA-Linux
shell$ git checkout v2018.2.0
```

### ソースコードのダウンロード

U-Boot のソースコードを以下の URL からダウンロードします。今回は U-Boot 本家からではなく、Xilinx が提供してる u-boot-xlnx を使います。

* [https://github.com/Xilinx/u-boot-xlnx.git](https://github.com/Xilinx/u-boot-xlnx.git)

```console
shell$ cd target/UltraZed-EG-IOCC/build-v2018.2
shell$ git clone https://github.com/Xilinx/u-boot-xlnx.git u-boot-xlnx-v2018.2
```

### xilinx-v2018.2 をチェックアウト

u-boot-xlnx の xilinx-v2018.2 というタグをチェックアウトして xilinx-v2018.2-ultrazed-eg-iocc という作業用のブランチを作ります。

```console
shell$ cd u-boot-xlnx-v2018.2
shell$ git checkout -b xilinx-v2018.2-ultrazed-eg-iocc xilinx-v2018.2
```

### UltraZed-EG-IOCC 用の各種ファイルを追加

UltraZed-EG-IOCC 用のファイルを追加してコミットします。追加するファイルの詳細は後述します。

```console
shell$ patch -p1 < ../../../../files/u-boot-xlnx-v2018.2-ultrazed-eg-iocc.diff
shell$ git add arch/arm/dts/zynqmp-uz3eg-iocc.dts
shell$ git add board/xilinx/zynqmp/zynqmp-uz3eg-iocc/psu_init_gpl.c
shell$ git add board/xilinx/zynqmp/zynqmp-uz3eg-iocc/psu_init_gpl.h
shell$ git add configs/xilinx_zynqmp_uz3eg_iocc_defconfig
shell$ git add include/configs/xilinx_zynqmp_uz3eg_iocc.h
shell$ git add --update
shell$ git commit -m "patch for UltraZed-EG-IOCC"
shell$ git tag -a xilinx-v2018.2-ultrazed-eg-iocc-0 -m "release xilinx-v2018.2-ultrazed-eg-iocc release 0"
```

### ブート時にメニューを表示させる

U-Boot の起動時にメニューを表示させるようにパッチをあてます。

```console
shell$ patch -p1 < ../../../../files/u-boot-xlnx-v2018.2-ultrazed-eg-iocc-bootmenu.diff
shell$ git add --update
shell$ git commit -m "[update] for boot menu command"
shell$ git tag -a xilinx-v2018.2-ultrazed-eg-iocc-1 -m "release xilinx-v2018.2-ultrazed-eg-iocc release 1"
```

詳細は次の記事を参考にしてください。

 * [「ZYBO用U-Bootでブート時にメニューを表示させる」@Qiita](https://qiita.com/ikwzm/items/c7932ebd1a7b40919241)

### 構築の準備

環境変数を設定します。アーキテクチャ(ARCH)に arm (arm64じゃないことに注意)を指定します。ここでは、クロスコンパイルに使うツールチェーン(CROSS_COMPILE) に aarch64-linux-gnu-を指定します。この変数は構築する環境にあわせてください。その後、UltraZed-EG-IOCC 用のコンフィギュレーション定義ファイルを使って構築の準備をします。

```console
shell$ cd u-boot-xlnx-v2018.2
shell$ export ARCH=arm
shell$ export CROSS_COMPILE=aarch64-linux-gnu-
shell$ make xilinx_zynqmp_uz3eg_iocc_defconfig
```

### u-boot の構築

```console
shell$ make
```

### Copy u-boot.elf

無事に u-boot.elf が出来たら、それを target/UltraZed-EG-IOCC/build-v2018.2 にコピーします。

```console
shell$ cp u-boot.elf target/UltraZed-EG-IOCC/build-v2018.2/u-boot.elf
```

## ファイルの説明

ここでは U-Boot を UltraZed-EG-IOCC にポーティングする際に新たに追加したファイルの説明をします。

### configs/xilinx_zynqmp_uz3eg_iocc_defconfig

U-Boot のコンフィギュレーション定義ファイルです。実はこのファイルの中身は u-boot-xlnx にすでにある xilinx_zynqmp_zcu102_revB_defconfig 等とそう変わるところはありません。異なっている箇所は CONFIG_SYS_CONFIG_NAME、CONFIG_IDENT_STRING、CONFIG_DEFAULT_DEVICE_TREE だけです。

なお、xilinx_zynqmp_uz3eg_iocc_defconfig には CONFIG_OF_EMBED=y が設定されています。つまり、U-Boot 用のデバイスツリーは外部ファイルではなく U-Boot の中に組み込まれています。

### arch/arm/dts/zynqmp-uz3eg-iocc.dts

U-Boot 用のデバイスツリーです。実はこのデバイスツリーは Linux Kernel を起動するデバイスツリーとまったく同じものです。このデバイスツリーの説明は Linux Kernel のところで説明します。

### include/configs/xilinx_zynqmp_uz3eg_iocc.h

U-Boot コンフィギュレーション定義ファイルに記述できない各種定数を定義しているファイルです。このファイルには次の定数が設定されています。```CONFIG_MENU_SHOW``` と ```CONFIG_CMD_BOOTMENU``` はブート時にメニューを表示させるための設定です。それ以外の定数は ```include/configs/xilinx_zynqmp.h``` のものをそのまま使っています。

```C:include/configs/xilinx_zynqmp_uz3eg_iocc.h
#ifndef __CONFIG_ZYNQMP_UZ3EG_IOCC_H
#define __CONFIG_ZYNQMP_UZ3EG_IOCC_H

#define CONFIG_ZYNQ_SDHCI0
#define CONFIG_ZYNQ_SDHCI1
#define CONFIG_SYS_I2C_ZYNQ
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
#define CONFIG_MENU_SHOW
#define CONFIG_CMD_BOOTMENU

#include <configs/xilinx_zynqmp.h>

#endif /* __CONFIG_ZYNQMP_UZ3EG_IOCC_H */
```

### include/configs/xilinx_zynqmp.h

ブート時にメニューを表示させるために ```include/configs/xilinx_zynqmp.h``` の ```CONFIG_EXTRA_ENV_SETTINGS``` を次のように修正します。具体的には ```"sd_uEnvtxt_load"``` 変数を追加し、```"uenvboot"``` 変数を修正します。さらに ```CONFIG_PREBOOT``` を次のように修正します。具体的には ```"sd_uEnvtxt_load"``` 変数を実行するようにします。これにより、プリブート時に ```uEnv.txt``` の内容を取り込むようになります。


```diff
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 59caeae..16dd174 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -161,6 +161,12 @@
 	"importbootenv=echo Importing environment from SD ...; " \
 		"env import -t ${loadbootenv_addr} $filesize\0" \
 	"sd_uEnvtxt_existence_test=test -e mmc $sdbootdev:$partid /uEnv.txt\0" \
+        "sd_uEnvtxt_load=" \
+		"if run sd_uEnvtxt_existence_test; then " \
+			"run loadbootenv; " \
+			"echo Loaded environment from ${bootenv}; " \
+			"run importbootenv; " \
+		"fi\0" \
 	"sata_root=if test $scsidevs -gt 0; then setenv bootargs $bootargs root=/dev/sda rw rootfstype=ext4; fi\0" \
 	"sataboot=load scsi 0 80000 boot/Image && load scsi 0 $fdt_addr boot/system.dtb && booti 80000 - $fdt_addr\0" \
 	"veloce=fdt addr f000000 && fdt resize" \
@@ -173,11 +179,6 @@
 		  "sf read $kernel_addr $kernel_offset $kernel_size && " \
 		  "booti $kernel_addr - $fdt_addr\0" \
 	"uenvboot=" \
-		"if run sd_uEnvtxt_existence_test; then " \
-			"run loadbootenv; " \
-			"echo Loaded environment from ${bootenv}; " \
-			"run importbootenv; " \
-		"fi; " \
 		"if test -n $uenvcmd; then " \
 			"echo Running uenvcmd ...; " \
 			"run uenvcmd; " \
@@ -229,7 +230,7 @@
 	DFU_ALT_INFO
 #endif
 
-#define CONFIG_PREBOOT		"run setup"
+#define CONFIG_PREBOOT		"run setup && run sd_uEnvtxt_load"
 
 /* Monitor Command Prompt */
 /* Console I/O Buffer Size */
```


### board/xilinx/zynqmp/zynqmp-uz3eg-iocc/psu_init_gpl.[ch]

これらファイルは[「UltraZed 向け Debian GNU/Linux (v2018.2版) の構築(Sample FPGA Design編)」@Qiita](https://qiita.com/ikwzm/items/aae6e17e7d08b089e010)で作ったハードウェア情報の中に入っています。ただし、U-Boot でハードウェア情報に含まれるファイルが必要になるのは u-boot.spl をビルドする場合です。今回は u-boot.spl は使いませんので、一度作っておいたファイルを使いまわしても問題ありません。