Debian Live で FPGA 開発ツール入りの live boot 環境を作る


- [武蔵野 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/musashino) 3日目 の記事です。

## ストーリー

- FPGA コンフィグのコンパイル（論理合成・配置配線）には強いマシンが欲しい。出先で借りれるものなら借りたい。
- が、FPGA 開発ツール類はインストーラのサイズが大きくなりがちであり、借り物マシンの上で環境を作るのにひと手間掛かる。（Linux 版だと）ディストリごとの差分等もあり簡単ではない場合がある。
- PC の修復用に、よく使うコマンド・パッケージ等を厳選したレスキューディスクを自分で作ってUSBメモリにインストールして使っている。
- そこで、FPGA ツールもその中に入れておけば、借り物マシンの環境を汚すことなく、すぐに起動して使えるのではないかと考えた。
- その過程を残したく思う。

## 作り方

### 環境

- debian stretch 上で行った
- 巨大なインクルードバイナリがあるので十分 HDD 領域を用意しておく
- `$ apt install live-build`
- wget が多用されるので、必要であれば wgetrc に proxy 設定を書き込んでおく

### 参考ページ

- 本家マニュアル : https://live-team.pages.debian.net/live-manual/html/live-manual/index.en.html
- "Debian Live で軽量なレスキューメディアを作ってみる" : http://d.hatena.ne.jp/MIZUNO/20120721/1342844487

### 基本手順

- スケルトンをコピーしてくる

```bash:
	$ mkdir -p live-custom/auto
	$ cp /usr/share/doc/live-build/examples/auto/* live-custom/auto/*
	$ ls
	build  clean  config
```

- auto/config 編集 (amd64 アーキテクチャで動かす場合)

```bash:
	#!/bin/sh
	set -e
	lb config noauto \
		--architectures amd64 \
		--archive-areas "main contrib non-free" \
		--bootappend-live "\
			boot=live components \
			nox11autologin \
			locales=ja_JP.UTF-8,en_US.UTF-8 \
			utc=no \
			timezone=Asia/Tokyo \
			keyboard-model=pc105 \
			keyboard-layouts=jp,us \
		"\
		"${@}"
```

32bit モードで作成したい場合は

```bash:
	     --architectures i386 \
	     --linux-flavours 686-pae \
```
を加えるとよい。
が、FPGA 開発ツールを動かすうえでは 64bit モードの方が都合がよいと思われる。

作成時に proxy が必要な場合は

```bash:
	     --apt-http-proxy http://proxy.hogehoge.com:8080/ \
```
を加える。

- スクリプト起動

```bash
	$ cd live-custom
	$ sudo lb build
```
live-image-{amd64/i386}.hybrid.iso が生成される。

これを USB メモリ等に dd でコピーすることで、EFI / BIOS 両方で起動する最低限の Live Disk ができる。

```bash
	$ dd if=live-image-{amd64/i386}.hybrid.iso of=/dev/{device_name} bs=16k
```

### カスタマイズ（レスキューディスクとして）

基本手順のみでは X も無く、起動するとターミナルだけの画面になってしまう。
レスキューに必要なツール群もない。
下記手順を施して使いやすくしていく。

- 追加パッケージを `live-custom/config/package-lists/custom.list.chroot` に1行1パッケージで記載する

```bash:
	acl
	acpi
	apt-file
	aptitude
	btrfs-progs
	crda
	cryptsetup
	curl
	console-data
	dnsutils
	fbterm
	firmware-b43-installer
	ftp
	gdisk
	git
	grub-pc
	lm-sensors
	lsof
	lzma
	lzop
	make
	mbr
	mmc-utils
	net-tools
	nkf
	openssh-client
	openssh-server
	openssh-sftp-server
	python
	rsync
	ruby
	samba
	smartmontools
	smbclient
	telnet
	time
	tmux
	uim
	uim-anthy
	uim-fep
	unifont
	vim
	w3m
	whois
	wpasupplicant
	bash-completion
	dvd+rw-tools
	firefox-esr-l10n-ja
	fonts-vlgothic
	gigolo
	gnome-mime-data
	gparted
	growisofs
	gthumb
	gvfs-backends
	handbrake
	libreoffice-calc
	libreoffice-impress
	libreoffice-l10n-ja
	libreoffice-writer
	mousepad
	network-manager-gnome
	pinta
	rdesktop
	ristretto
	thunar-archive-plugin
	thunar-media-tags-plugin
	vlc
	x11vnc
	xarchiver
	xfburn
	xfce4
	xfce4-battery-plugin
	xfce4-indicator-plugin
	xfce4-power-manager
	xfce4-screenshooter
	xfce4-terminal
	xinetd
	xtightvncviewer
	xvkbd
```

task-japanese-desktop 等を選択することでまとめてインストールできるが、個別に吟味してパッケージを取捨選択することで領域の節約になる

- chroot 中のフックを指定する
- 
ルートファイルシステムがマウントされた後のOSのコンフィグ等に手をつけたければこちらから。
/usr/share/doc/live-build/examples/hooks/minimal.hook.chroot などを参考に、以下を追記して config/hooks/live/0099-custom.hook.chroot に保存する。

```bash:
# Removing unused packages
#for PACKAGE in apt-utils aptitude man-db manpages info wget
for PACKAGE in live-boot-doc live-config-doc nano light-locker lightdm gnome-user-guide
do
	if ! apt-get remove -f --purge --yes "${PACKAGE}"
	then
		echo "WARNING: ${PACKAGE} isn't installed"
	fi
done
apt-get autoremove --yes || true

# prepare apt-file for searching
apt-file update

# make fbterm accessible from users
chmod u+s /usr/bin/fbterm

# add some lines to bashrc
echo "alias fbterm='fbterm --font-size=16'" >> /etc/skel/.bashrc

# apt-proxy
echo "#Acquire::http::Proxy \"http://proxy.yoyodyne.com:18023/\";" >> /etc/apt/apt.conf

# replace uim-fep on / off command to "ctrl+space"
sed -i -e 's/<Shift>\ /<Control>\ /' /usr/share/uim/generic-key-custom.scm

# re-enable ssh password auth (vulnerable !)
sed -i -e '/PasswordAuthentication no/d' /etc/ssh/sshd_config

# set up x11vnc
echo "x11vnc-stream 5900/tcp" >> /etc/services

# Removing unused files
find . -name *~ -print0 | xargs -0 rm -f
```
lightdm をアンインストールしてしまうことで強引にログインマネージャが起動しないようにしたり、ターミナルのみでの作業時も日本語ファイル名等が使いやすいように uim-fep を入れたり、外からのアクセスを待ち受けるデーモンの設定等を書き換えたりした。

- chroot の外でのフックを指定する

ルートファイルシステムがマウントされる前のフックを掛けたければこちらから。
config/hooks/live/0099-custom.hook.binary を配置して編集する。

```
#!/bin/sh
set -e
# remove install menu from isolinux
sed -i -e '/include install.cfg/d' isolinux/menu.cfg

# set boot timeout 10s
sed -i -e 's/timeout 0/timeout 100/' isolinux/isolinux.cfg
```

boot 時のスプラッシュ画面から live boot では使わない install メニューを削除する処理、タイムアウト時間を延ばす処理を書いてある

- chroot 内に含めるファイル等を指定する

設定ファイル等、直接配置したいファイルは config/includes.chroot/ 以下をルートパーティションとした相対ディレクトリに配置しておく。

```
config/includes.chroot/etc/root/.vimrc
config/includes.chroot/etc/skel/vimrc
config/includes.chroot/etc/xinetd.d/x11vnc-stream
```
などが例。

- ここまでカスタムしたものは https://github.com/homelith/debian-live-custom に置いてあります。

### カスタマイズ（FPGA 開発ツール編）

今回は https://qiita.com/homelith/items/a80a5e4d45ea9280145a の環境を再コンパイルできることを目標にした。

- Quartus Lite に OpenCL ツールキットを組み合わせた状態でインストール

/opt/intelFPGA_lite/18.1 以下に Quartus Prime Lite, /opt/intelFPGA/18.1 以下に Quartus Prime Standard をインストールし、Standard 側は hld ディレクトリのみを残して Lite 側のディレクトリにリンクを張る。

以下、インストール時に指定したオプション (Quartus Prime Lite)

```
x Quartus Prime (includes Nios II EDS) (6293 MB)
- Quartus Prime Help (498.2 MB)
x Devices
    - Arria II (536.5 MB)
    - Cyclone IV (516.3 MB)
    x Cyclone 10 LP (293.5 MB)
    x Cyclone V (1225.5 MB)
    x MAX II/V (13.1 MB)
    x MAX 10 FPGA (341.5 MB)
x ModelSim - Intel FPGA Starter Edition (Free) (4134.9 MB)
- ModelSim - Intel FPGA Edition (4134.9 MB)
```

(Quartus Prime Standard)

```
x Quartus Prime (includes Nios II EDS) (7191 MB)
- Quartus Prime Help (498.2 MB)
x Devices
    - Arria II (754.2 MB)
    - Arria 10 Part 1 (3322.7 MB)
    - Arria 10 Part 2 (4117.7 MB)
    - Arria 10 Part 3 (4358.1 MB)
    - Arria V (1495.3 MB)
    - Arria V GZ (2059.5 MB)
    - Cyclone IV (516.3 MB)
    x Cyclone 10 LP (293.5 MB)
    x Cyclone V (1225.5 MB)
    x MAX II/V (13.1 MB)
    x MAX 10 FPGA (341.5 MB)
    - Stratix IV (717.0 MB)
    - Stratix V (3150.6 MB)
- ModelSim - Intel FPGA Starter Edition (Free) (4134.9 MB)
- ModelSim - Intel FPGA Edition (4134.9 MB)
x DSP Builder (298.2 MB)
x Intel FPGA SDK for OpenCL (1662.8 MB)
```

modelsim を使いたい場合は https://wiki.archlinux.jp/index.php/Altera_Design_Software の [Archlinux との互換性] -> [カーネル 4.x 以上] の項のワークアラウンドなどを参考に設定し使えるようにしておく

- chroot 内へのバイナリインクルード

インストールされたファイルを config/includes.chroot/opt 以下へ丸ごと移植する。
また、PATH を通すスクリプトなどを config/includes.chroot/home/user （出来上がった live ディスクのログインユーザのホーム）などに配置しておくとよい。

以下、config/includes.chroot/home/user/setup_intelFPGA.sh として保存したものの例を記載する。

```
# usage : source {this_file.sh} {path_to_install_dir (ex. /opt/intelFPGA/17.1)}

#LICENSE_FILE=/opt/intelFPGA/license/{license_file}.dat
DEFAULT_BSP=c5gt_eth_custom

if [ -z "$1" ]; then
	echo "usage : source {this_file.sh} {path_to_install_dir (ex. /opt/intelFPGA/17.1)}"
else
	export QUARTUS_ROOTDIR="$1"/quartus
	export MODELSIM_ASE_DIR="$1"/modelsim_ase
	export MODELSIM_AE_DIR="$1"/modelsim_ae
	export INTELFPGAOCLSDKROOT="$1"/hld
	export ALTERAOCLSDKROOT="$INTELFPGAOCLSDKROOT"
	export SOPC_KIT_NIOS2="$QUARTUS_ROOTDIR"/../nios2eds
	export PATH=$PATH:"$QUARTUS_ROOTDIR"/bin:"$QUARTUS_ROOTDIR"/linux64:"$QUARTUS_ROOTDIR"/../qsys/bin:"$QUARTUS_ROOTDIR"/sopc_builder/bin:"$QUARTUS_ROOTDIR"/sopc_builder/model/bin:"$SOPC_KIT_NIOS2"/bin:"$INTELFPGAOCLSDKROOT"/linux64/bin:"$INTELFPGAOCLSDKROOT"/bin:"$MODELSIM_AE_DIR"/bin:"$MODELSIM_ASE_DIR"/bin:"$QUARTUS_ROOTDIR"/../embedded
	export AOCL_BOARD_PACKAGE_ROOT="$INTELFPGAOCLSDKROOT"/board/"$DEFAULT_BSP"
	export LD_LIBRARY_PATH="$AOCL_BOARD_PACKAGE_ROOT"/linux64/lib:"$INTELFPGAOCLSDKROOT"/host/linux64/lib
	export QUARTUS_64BIT=1
	#export ACL_HAL_DEBUG=99
	#export ACL_PCIE_DEBUG=99
	if [ -z "$LM_LICENSE_FILE" ]; then
		export LM_LICENSE_FILE="$LICENSE_FILE"
	else
		export LM_LICENSE_FILE=$LM_LICENSE_FILE:"$LICENSE_FILE"
	fi
fi
```

- chroot インクルードから末尾に ~ がついたファイルを除去する

これをやらないと iso が生成されない。恐らくバックアップファイルを削除する処理が走っているものと思われるが、それがうまく動かず止まってしまっている？ 

quartus 18.1 lite の場合は下記を削除すると動いた。

```
config/includes.chroot/opt/intelFPGA_lite/18.1/modelsim_ase/docs/tcl_help_html/TclLib/modules/contents.html~
config/includes.chroot/opt/intelFPGA_lite/18.1/quartus/common/tcl/packages/tclsoap-1.6.7/SOAP.tcl~
config/includes.chroot/opt/intelFPGA_lite/18.1/quartus/common/tcl/packages/tclsoap-1.6.7/xpath.tcl~'
```

- 上記の構成を入れたところ、出来上がった iso ファイルは 7.1 GB になった。8 GB 以上の USB メモリ等に向かって書き込むことで使用可能になる。

## 使い方

- EFI ブート時は secure boot をオフにしないと起動しないことに注意する。
- boot 後、"user" という名前のユーザで自動ログインされた状態のコンソール画面が見える。
- `$ startx` で xfce を起動
- terminal を起動して `$ source setup_intelFPGA.sh /opt/intelFPGA_lite/18.1`
- これで quartus 初め他の開発ツールコマンドが使える。長大なダウンロード＆インストール時間要らずとなった。

- Cyclone V GT Dev kit 用の OpenCL BSP (https://qiita.com/homelith/items/a80a5e4d45ea9280145a) を使ってコンパイルフローを流してみた図
![live-boot.png](https://qiita-image-store.s3.amazonaws.com/0/216085/815bf09e-32ae-ce33-100e-74deaf95827e.png)

ホームディレクトリはデフォルトではメモリ上に展開されるので、コンパイル用のワーキングディレクトリとして使用するとメモリが圧迫される。
HDD / USB メモリ等のどこか別の書き込み可能領域をマウントしてから使用する等で回避することができる。

上記の例ではメモリ8GのノートPC上で動作させたが、Cyclone V の規模であれば OpenCL からのコンパイルフローもすべてオンメモリで通すことができた。