WSL上にRaspberry Pi OS(RaspbianBuster)をQEMUエミュレーターで動かす(Raspi3マシン)

# はじめに
VSCodeのRemort SSHにてRaspberry Pi OSに接続し C++のクロスコンパイルを実現しようとしたものの、リモート側とリモートホスト側がWindowsという組み合わせでは「vscode-server」はインストールできたのだが、その後の接続が安定しないのです。
リモートホスト側をLinuxにすれば、重いですがVSCode上でデバッグが出来るまでになりました。

https://qiita.com/yaju/items/5ec5c4df1db1f8ebbac7

Windows 10には、WSL(Windows Subsystem for Linux)というLinuxバイナリ実行可能ファイルをネイティブに実行するための互換性レイヤーが備わっているので、これでQEMUエミュレーターを動かしてみました。

【2023/08/27追記】
raspios-bullseye で構築された記事を見つけましたのでリンクしておきます。

https://hiro20180901.com/2023/04/24/raspberry-pi-os-64-bit-runs-qemu-720-vritual-machine/

# 環境
* Windows 10 Home 64bit(21H1) ※MacのParallels Desktop 1５ Standard Edition上で使用
* QEMU 5.2
* WSL(Ubuntu 20.04 LTS)

※WSL2は、Parallels Desktop Standard Editionだと「ネストされた仮想化を有効にする」が使用不可で断念
[ParallelsでWindows 10のWSL2を使う](https://sugamasao.hatenablog.com/entry/2020/06/09/090000)

## WSLでGUI環境
QEMUのオプション`nographic`を指定すればGUI環境は不要になるのですが、GUI環境で動作させてみたかった。

本当はWSL2のGUI対応(WSLg)のプレビューが始まったので「WSLg」でやりたかったのですが、自分の環境では「Parallels Desktop Standard Edition」を使用しているため、WSL2が使用できませんでした。

# 導入手順
## QEMUのインストール
QEMUは、CPUエミュレーションをするためのソフトウェアになります。

Ubuntu 20.04 LTSでは「sudo apt install -y qemu-system」とすると、QEMU 4.2.1がインストールされます。
しかし、QEMU 5.1以降でUSBコントローラをサポートしたことでネットワーク等が使用できるようになったので、QEMU 4.2.1では意味がありません。
最新のQEMU 6.0があるのですが、コンパイル方法で躓いて諦めました。

UbuntuにはサーバーバックポートのPPA（Personal Package Archive）があり、QEMU 5.２をインストールすることができました。
[第419回　長期サポート版で改めて見直す，PPAとのお付き合い](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0419)

https://launchpad.net/~canonical-server/+archive/ubuntu/server-backports

```bash
$ sudo add-apt-repository ppa:canonical-server/server-backports
$ sudo apt-get update
$ sudo apt install -y qemu-system

$ qemu-system-aarch64 -version
QEMU emulator version 5.2.0 (Debian 1:5.2+dfsg-9ubuntu3~backport20.04-202104240125~ubuntu20.04.1)
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers
```

## GUI環境の構築
GUI環境の構築のために下記サイトを参考にWSL上にX11アプリケーションを実行できる環境にしました。
**GUI環境は不要な場合、これより下の項目の作業は不要になります。**

https://dev.classmethod.jp/articles/wsl-x-window/

### X11のインストール

```bash
sudo apt install x11-apps
```

### VcXsrvのインストール
SourceForge.netからVcXsrvをダウンロードします。
https://sourceforge.net/projects/vcxsrv/

### VcXsrvを起動
スタートメニューからVcXsrvフォルダを開き、XLaunchアイコンをクリックします。
画面の設定は下記サイトを参照してください。
https://dev.classmethod.jp/articles/wsl-x-window/

### WSLに設定
タスクバーの右横にある「通知領域」にXLaunchアイコンがあるので、マウスを合わせるとツールチップスにアドレスが表示されます。そのアドレスを設定します。**(PCによって値が異なります。)**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/20cc25c1-b0d0-48ed-6506-783999346d81.png)

```bash
$ export DISPLAY=48C2:0.0
$ echo $DISPLAY
```

ターミナルを起動したときに環境変数の追加を自動でやってほしい場合「.bashrc」を編集すればいいです。

```bash:.bashrc
$ sudo nano ~/.bashrc

# 最下行に追加
export DISPLAY=48C2:0.0
```

### xeyesの確認
Windowsのデスクトップ上に、`xeyes`等ののX11アプリケーションが表示されるのを確認します。

```bash
$ xeyes
```

xeyesは2つの動眼を表示するグラフィカルなプログラムで、動眼がまるでマウスカーソルを見ているかのようにその動きを追うようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/c152a353-338c-20da-54ea-eed74fc35933.png)

# GUI環境
GUI環境は、下記サイトを参考に導入します。

https://qiita.com/yaju/items/edf548efd18f0eaab94a

RaspberryPi3フォルダを作成して、run.shファイルを新規作成します。

```bash
$ mkdir RaspberryPi3
$ cd RaspberryPi3
$ touch run.sh
$ nano run.sh
```

Linux版との違いとしてWSLでは容量が少ないことを考慮して、イメージなどはWindowsフォルダ「/mnt/c/RaspberryPi3」を指定しています。

```bash:run.sh
#!/bin/sh
cd `dirname $0`

qemu-system-aarch64 \
-m 1024 \
-M raspi3 \
-kernel /mnt/c/RaspberryPi3/kernel8.img \
-dtb /mnt/c/RaspberryPi3/bcm2710-rpi-3-b.dtb \
-drive format=raw,file=/mnt/c/RaspberryPi3/2020-08-20-raspios-buster-arm64.img \
-append "console=ttyAMA0 root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4 dwc_otg.fiq_fsm_enable=0 bcm2708_fb.fbwidth=1280 bcm2708_fb.fbheight=720" \
-serial stdio \
-no-reboot \
-device usb-kbd \
-device usb-tablet \
-device usb-net,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22
```

ターミナル上でrun.shに実行権限を追加してから実行すれば、 数分でRaspberry Pi OSが起動します。
Linux版と比べて何か表示されるまでに数分かかります。

```bash
$ chmod 755 run.sh
$ ./run.sh
```

XLaunchアイコンが起動していない場合、下記のエラーになります。

```bash
Unable to init server: Could not connect: Connection refused
gtk initialization failed
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/5599818b-abe8-5f95-0367-bd0b9f6b9fb2.png)

# CUI環境
今回は、Raspi3マシンのみとします。
GUI版に合わせたためデスクトップイメージを使用していますが、用途によってはライトイメージを使用してもいいと思います。また、その際にはイメージサイズも4Gと小さくしてもいいでしょう。

イメージサイズを8Gに変更します。

```bash
$ qemu-img resize /mnt/c/RaspberryPi3/2020-08-20-raspios-buster-arm64.img 8G
WARNING: Image format was not specified for '/mnt/c/RaspberryPi3/2020-08-20-raspios-buster-arm64.img' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
Image resized.
```

RaspberryPi3フォルダを作成して、run.shファイルを新規作成します。

```bash
$ mkdir RaspberryPi3
$ cd RaspberryPi3
$ touch run.sh
$ nano run.sh
```

GUI版との違いとして画面表示なしオプションの「-nographic」を追加することで、キーボードやマウスなどのデバイスや画面サイズの指定などを省いています。

```bash:run.sh
#!/bin/sh
cd `dirname $0`

qemu-system-aarch64 \
-m 1024 \
-M raspi3 \
-kernel /mnt/c/RaspberryPi3/kernel8.img \
-dtb /mnt/c/RaspberryPi3/bcm2710-rpi-3-b.dtb \
-drive format=raw,file=/mnt/c/RaspberryPi3/2020-08-20-raspios-buster-arm64.img \
-append "console=ttyAMA0 root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4 dwc_otg.fiq_fsm_enable=0" \
-nographic \
-device usb-net,netdev=net0 \
-netdev user,id=net0,hostfwd=tcp::2222-:22
```

ターミナル上でrun.shに実行権限を追加してから実行すれば、 数分でRaspberry Pi OSが起動します。
Linux版と比べて何か表示されるまでに数分かかります。

```bash
$ chmod 755 run.sh
$ ./run.sh
```

ログインを求められます。
デフォルトの管理者 ユーザー名:pi パスワード:raspberry

ネットに繋がっているか確認します。`eth0` または `usb0` が表示されるはずです。

```bash
$ ip addr
2: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
```

SSHを有効化する

```bash
$ sudo systemctl enable ssh --now
```

空き容量を増やします。
設定画面が表示されるので、「7 Advanced Options -> A1 Expand Filesystem」を選択する。

```bash
$ sudo raspi-config
```

スワップ領域も少ないので下記コマンドで修正を行います。

```bash
$ sudo nano /etc/dphys-swapfile
/etc/dphys-swapfile

CONF_SWAPSIZE=2048
```

設定を反映します。

```
$ sudo dphys-swapfile install
$ sudo dphys-swapfile swapon
$ swapon　-s
```

# VSCode
クロスコンパイル環境を実現したいため、Remort SSHを使用してC++による開発を行えるようにします。

## Remort SSH
Remort SSHするだけなら、Raspberry Pi OS側にVSCodeをインストールする必要はありません。
VS Code Serverは、ネットワークが遅いのでインストールが完了するまでに30分くらいかかります。

開発言語にC++として拡張機能をインストールしました。ネットワークが不安定なので何度か繰り返したりしました。

* C/C++
* C/C++ IntelliSense

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/2c912fa2-ed9c-d92f-b379-7cc00190972d.png)

# 最後に
これで、WindowsならVirtual BoxでLinuxをインストールしなくても、WSLを使用すればいいです。

どうしてもWSL2でやってみたくなったため、「Parallels Desktop 16 for Mac Standard Edition」から「Parallels Desktop for Mac Pro Edition」にアップグレードしました。
これで「ネストされた仮想化を有効にする」ことができるため、WSL2やWSLgやqemu-kvmなどいろいろ試せそうです。

【2021/07/30追記】 WSL2版の記事を書きました。

https://qiita.com/yaju/items/bb91ea2bf84aac92243c