bootgen を Debian GNU/Linux、Ubuntu で動かす

はじめに
-----------------------------------------------

bootgen は バイナリファイルを統合してデバイスブートイメージを生成する Xilinx 社が提供している開発ツールです。主に次の用途に使用します。

  1. Zynq や ZynqMP 等のシステムオンチップ(SoC) のブートイメージ(boot.bin) を生成      
     参考: [「Ultra96 向け Debian GNU/Linux (v2018.2版) の構築(BOOT.BIN編)」@Qiita][BOOT.BIN の構築]
  2. FPGA をコンフィギュレーションする際にビットストリームファイル(xxxx.bit) をバイナリファイル(xxxx.bin) に変換     
     参考: [「UltraZed 向け Debian GNU/Linux (v2018.2版) で FPGA をコンフィギュレーション例」@Qiita][コンフィギュレーション例]
  
bootgen の詳細は [「Bootgen ユーザー ガイド」][ug1283] を参照してください。

さて、この bootgen ですが、もともと Xilinx Vivado および Xilinx SDK に含まれていたプログラムで、実行するには Xilinx Vivado または Xilinx SDK がインストールされている環境でしか動きません。また、2019.2 からは Xilinx SDK が Vitis に統合されたこともあってか bootgen だけが別インストールになったりちょっと不便になりました。

幸い、bootgen は Xilinx 社がソースコードを github で公開しています。

  * https://github.com/Xilinx/bootgen

これをビルドすれば bootgen がお好みの環境で動きます。嬉しいことに x86 アーキテクチャだけでなく arm64 アーキテクチャでも動作するため、[「UltraZed/Ultra96/Ultra96-V2 向け Debian GNU/Linux (v2019.1版) ブートイメージの提供」][ZynqMP-FPGA-Linux]で紹介した環境であれば、そのままターゲットの上で bootgen が実行できて地味に便利だったりします。この記事では Debian GNU/Linux または Ubuntu でビルドして実行する例を紹介します。

普通にビルドしてインストールする方法
-----------------------------------------------

### 準備

ビルドするためにはコンパイラおよび OpenSSL v1.1.1 が必要です。

セルフコンパイルする際は、ビルドする環境に OpenSSL の開発環境をインストールする必要があります。Debian GNU/Linux や Ubuntu の場合は、apt install で libssl-dev パッケージをインストールしておきます。
クロスコンパイルする際は、ビルドする環境にターゲットアーキテクチャ用のOpenSSL の開発環境をインストールする必要があるのですが、意外と面倒です。この記事ではクロスコンパイルの方法には触れません。

### ダウンロード

以下の github のリポジトリをダウンロード(clone)します。

* https://github.com/Xilinx/bootgen

```console
shell# git clone https://github.com/Xilinx/bootgen
Cloning into 'bootgen'...
remote: Enumerating objects: 146, done.
remote: Counting objects: 100% (146/146), done.
remote: Compressing objects: 100% (95/95), done.
remote: Total 146 (delta 58), reused 138 (delta 50), pack-reused 0
Receiving objects: 100% (146/146), 386.16 KiB | 466.00 KiB/s, done.
Resolving deltas: 100% (58/58), done.
```

### ビルド

make コマンドを実行すればふつ〜に bootgen がビルド出来ます。

```console
shell# cd bootgen
shell# 
shell# make
  :
  (中略)
  :
echo Building executable file: bootgen...
Building executable file: bootgen...
g++ -std=c++0x -O -Wall -Wno-reorder -Wno-deprecated-declarations   -o bootgen \
bif.tab.o bif.yy.o reginit.tab.o reginit.yy.o cmdoptions.tab.o cmdoptions.yy.o \
authentication.o authentication-zynq.o authentication-zynqmp.o authkeys.o binar\
y.o binfile.o bitutils.o options.o bifoptions.o bootheader.o bootheader-zynq.o \
bootheader-zynqmp.o bootimage.o bootimage-zynq.o bootimage-zynqmp.o checksum.o \
elftools.o encryption.o encryptutils.o encryptionkeys.o encryption-zynq.o encry\
ption-zynqmp.o hash.o imageheadertable.o imageheadertable-zynq.o imageheadertab\
le-zynqmp.o Keccak-compact.o logger.o readimage.o readimage-zynq.o readimage-zy\
nqmp.o verifyimage.o main.o mcsfile.o outputfile.o parsing.o partition.o partit\
ionheadertable.o partitionheadertable-zynq.o partitionheadertable-zynqmp.o regi\
nit.o -lssl -lcrypto
shell# 
shell# file bootgen
bootgen: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamica\
lly linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildI\
D[sha1]=9ea6dc2ff0979a37bd4e6
```

### インストール

ビルドした bootgen を実行パスの通っているところにコピーします。ここでは /usr/local/bin にコピーしています。

```console
shell# cp bootgen /usr/local/bin
shell# which bootgen
/usr/local/bin/bootgen
```

Debian Package 化してインストールする方法
-----------------------------------------------

### 準備

ビルドするためにはコンパイラおよび OpenSSL v1.1.1 が必要です。さらに Debian Package をビルドするための各種ツールが必要です。

```console
shell$ sudo apt install debhelper quilt dh-exec libssl-dev
  :
  (中略)
  :
```

### ダウンロード

以下の URL に bootgen を Debian Package にするリポジトリを置いておきます。このリポジトリは筆者が https://github.com/Xilinx/bootgen を fork して、Debian Package をビルドするための各種ファイルを追加したものです。ブランチが master ではなく 2019.2-develop であることに注意してください。

* https://github.com/ikwzm/bootgen

```console
shell$ git clone -b 2019.2-develop https://github.com/ikwzm/bootgen.git
Cloning into 'bootgen'...
remote: Enumerating objects: 160, done.
remote: Counting objects: 100% (160/160), done.
remote: Compressing objects: 100% (104/104), done.
remote: Total 160 (delta 63), reused 150 (delta 53), pack-reused 0
Receiving objects: 100% (160/160), 389.17 KiB | 397.00 KiB/s, done.
Resolving deltas: 100% (63/63), done.
```

### ビルド

debian/rules binary で Debian Package をビルドします。

```console
shell$ cd bootgen
shell$ sudo debian/rules binary
  :
  (中略)
  :
dpkg-deb: building package 'bootgen' in '../bootgen_2019.2-1_arm64.deb'.
dpkg-deb: building package 'bootgen-dbgsym' in '../bootgen-dbgsym_2019.2-1_arm64.deb'.
```

一つ上のディレクトリに bootgen_2019.2-1_arm64.deb が出来ていればビルド成功です。

```console
shell$ dpkg --info ../bootgen_2019.2-1_arm64.deb
 new Debian package, version 2.0.
 size 202168 bytes: control archive=596 bytes.
     338 bytes,    10 lines      control
     192 bytes,     3 lines      md5sums
 Package: bootgen
 Version: 2019.2-1
 Architecture: arm64
 Maintainer: ikwzm <ichiro_k@ca2.so-net.ne.jp>
 Installed-Size: 758
 Depends: libc6 (>= 2.17), libgcc1 (>= 1:3.0), libssl1.1 (>= 1.1.1), libstdc++6 (>= 5.2)
 Section: utils
 Priority: optional
 Homepage: <https://github.com/Xilinx/bootgen>
 Description: Bootgen for Xilinx Zynq and ZU+SoCs
```

### インストール

Debian Packege を dpkg を使ってインストールします。

```console
shell$ sudo dpkg --install ../bootgen_2019.2-1_arm64.deb
Selecting previously unselected package bootgen.
(Reading database ... 85254 files and directories currently installed.)
Preparing to unpack ../bootgen_2019.2-1_arm64.deb ...
Unpacking bootgen (2019.2-1) ...
Setting up bootgen (2019.2-1) ...
```

```console
shell$ which bootgen
/usr/bin/bootgen
```

```console
shell$ bootgen


****** Xilinx Bootgen v2019.2
  **** Build date : Jan 16 2020-08:00:00
    ** Copyright 1986-2019 Xilinx, Inc. All Rights Reserved.

------------------------------------------------------------------------------+
                       COMMAND LINE OPTIONS                                   |
-------------------------------+----------------------------------------------+
 -arch              [options]  | Xilinx Architecture                          |
                               | options: [zynq, zynqmp, fpga]                |
-------------------------------+----------------------------------------------+
 -image            <filename>  | Input Boot Image File (.bif)                 |
-------------------------------+----------------------------------------------+
 -o                <filename>  | Output filename in MCS/BIN format            |
-------------------------------+----------------------------------------------+
 -w                 [options]  | Overwrite mode                               |
                               | options: [on, off]                           |
-------------------------------+----------------------------------------------+
 -encrypt           [options]  | AES Key storage in chip (Zynq only)          |
                               | options: [bbram, efuse]                      |
-------------------------------+----------------------------------------------+
 -p                  <string>  | Part name                                    |
-------------------------------+----------------------------------------------+
 -efuseppkbits     <filename>  | Generate PPK hash for e-fuse                 |
-------------------------------+----------------------------------------------+
 -generate_hashes              | Generate SHA hashes (PKCS#1v1.5)             |
-------------------------------+----------------------------------------------+
 -spksignature     <filename>  | Generate SPK signature file                  |
-------------------------------+----------------------------------------------+
 -fill             <hex-byte>  | Fill byte for padding                        |
-------------------------------+----------------------------------------------+
 -split             [options]  | Split partitions to diff files               |
                               | options: [bin, mcs]                          |
-------------------------------+----------------------------------------------+
 -padimageheader    [options]  | Pad header tables                            |
                               | options: [0, 1]                              |
-------------------------------+----------------------------------------------+
 -process_bitstream [options]  | Outputs bitstream in bin/mcs format          |
                               | options: [bin, mcs]                          |
-------------------------------+----------------------------------------------+
 -generate_keys     [options]  | Generate authentication keys                 |
                               | options: [pem, rsa, obfuscatedkey]           |
-------------------------------+----------------------------------------------+
 -dual_qspi_mode    [options]  | Generate 2 output files for Dual QSPI        |
                               | options: [parallel, stacked <size>]          |
-------------------------------+----------------------------------------------+
 -log               [options]  | Generate log file                            |
                               | options: [error, warning, info, debug, trace]|
-------------------------------+----------------------------------------------+
 -zynqmpes1                    | Generate boot image for (1.0)ES1             |
-------------------------------+----------------------------------------------|
 -nonbooting                   | Generate an intermediate boot image          |
-------------------------------+----------------------------------------------|
 -encryption_dump              | Generate encryption log file                 |
-------------------------------+----------------------------------------------+
 -verify                       | Verify BootImage authentication              |
-------------------------------+----------------------------------------------+
 -h | -help                    | Print the help summary                       |
-------------------------------+----------------------------------------------+
 -bif_help                     | Print the BIF help summary                   |
-------------------------------+----------------------------------------------+
 Note     : For more info on bootgen options, use the command                 |
            bootgen -help <option>                                            |
 Example  : bootgen -help efuseppkbits                                        |
------------------------------------------------------------------------------+

```

参考
-----------------------------------------------

* https://github.com/Xilinx/bootgen
* https://github.com/ikwzm/bootgen
* [「Bootgen ユーザー ガイド」 @Xilinx][ug1283]
* [「UltraZed/Ultra96/Ultra96-V2 向け Debian GNU/Linux (v2019.1版) ブートイメージの提供」@Qiita][ZynqMP-FPGA-Linux]
* [「Ultra96 向け Debian GNU/Linux (v2018.2版) の構築(BOOT.BIN編)」@Qiita][BOOT.BIN の構築]
* [「UltraZed 向け Debian GNU/Linux (v2018.2版) で FPGA をコンフィギュレーション例」@Qiita][コンフィギュレーション例]

[ZynqMP-FPGA-Linux]: https://qiita.com/ikwzm/items/0c6f110aa19e368af03d "UltraZed/Ultra96/Ultra96-V2 向け Debian GNU/Linux (v2019.1版) ブートイメージの提供"
[BOOT.BIN の構築]: https://qiita.com/ikwzm/items/af4420edd262e14feef9 "Ultra96 向け Debian GNU/Linux (v2018.2版) の構築(BOOT.BIN編)"
[コンフィギュレーション例]: https://qiita.com/ikwzm/items/935236c7de01c578aeff "UltraZed 向け Debian GNU/Linux (v2018.2版) で FPGA をコンフィギュレーション例"
[ug1283]: https://www.xilinx.com/support/documentation/sw_manuals_j/xilinx2018_3/ug1283-bootgen-user-guide.pdf "UG1283 Bootgen ユーザー ガイド"