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

# はじめに
前回、WSLでGUI環境とCUI環境の構築した記事を書きました。

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

自分のPC環境は、Mac上に「Parallels Desktop 16 for Mac」にてWindows 10で使用していたのですが、WSL2の環境にしようとした際に、「Parallels Desktop 16 for Mac Standard Edition」では「ネストされた仮想化を有効にする」設定が見当たらずWSL2が作成できないことが分かりました。
そこで「Parallels Desktop for Mac Pro Edition」にアップグレードしました。これで「ネストされた仮想化を有効にする」設定が表示されチェックオンができるようになり、WSL2の環境を作成できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/e022ede9-7979-3be8-4ff9-5d0919ac3ba3.png)

※記事内容は、WSL版とほぼ同じ内容となります。キャプチャ画像もWSL版と一部共有しています。

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

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

# 環境
* Windows 11 Home 64bit プレビュー版 ※MacのParallels Desktop 16 Pro Edition上で使用
* QEMU 5.2
* WSL2(Ubuntu 20.04 LTS)

※WSLgを試したかったため、Windows Insider Programに参加してDevチャネルを選択していたら、Windows 11 プレビュー版になりました。

# 導入手順
## WSL2をアップデート
WSLでLinuxのGUIアプリを動かす仕組みは、「WSLg(Windows Subsystem for Linux GUI)」と呼ばれています。
WSL2を最新版にすれば、WSLgを使用することができます。※WSLgはWSL2でのみサポートされます。

自分の環境ではWSL2をインストール済みであったため、 WSL2自体のアップデートを行う必要がありました。

```
wsl --update
```

https://www.eisbahn.jp/yoichiro/2021/06/wslg.html

なお、Windows 11でWSL2自体を最初からインストールした場合、最初からLinuxのGUIアプリケーションを実行できるようになっています。

https://astherier.com/blog/2021/07/windows11-install-wsl2-and-wslg/

https://news.mynavi.jp/article/20210723-1915331/

### 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)

## 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
```

## カーネルとデバイスツリーソースファイルの抽出
カーネルファイル「kernel8.img」とデバイスツリーソースファイル「bcm2710-rpi-3-b.dtb」は、イメージファイルの中から抽出する必要があります。
イメージファイルの中からファイルを抽出するのに、ループバック・デバイスを使います。
※WSLと違ってWSL2では、ループバック・デバイスが使用できるようになっていました。

WSL2上で、「/mnt/c/RaspberryPi3」をカレントディレクトリとして以下の作業を行なっています。
イメージファイルが「/mnt/c/RaspberryPi3/2020-08-20-raspios-buster-arm64.img」にある状態にしています。

```bash
$ sudo losetup --show -fP 2020-08-20-raspios-buster-arm64.img
/dev/loop0
```

loop0の部分は、PCによって違うので書き換えてください。

```bash
$ sudo mount /dev/loop0p1 ~/raspios
$ cp ~/raspios/kernel8.img ~/raspios/bcm2710-rpi-3-b.dtb .
$ sudo umount ~/raspios
$ sudo losetup -d /dev/loop0
```

/mnt/c/RaspberryPi3/フォルダには3ファイルがある状態になっています。

* 2020-08-20-raspios-buster-arm64.img
* kernel8.img
* bcm2710-rpi-3-b.dtb

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

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

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

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

Linux版との違いとしてWSL2では容量が少ないことを考慮して、イメージなどは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が起動します。
WSL版と違い何か表示されるまで数分待つ必要がありません。

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

![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が起動します。
WSL版と違い何か表示されるまで数分待つ必要がありません。

```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

C++の拡張機能のダウンロードがどうにも出来そうもなかったため、下記サイトから「cpptools-linux-aarch64.vsix」を直接ダウンロードして、c:¥tempフォルダに保存しました。
https://github.com/microsoft/vscode-cpptools/releases

SCPコマンドでホスト側のDownloadsフォルダにファイルを転送しました。23MBに4分かかっています。

```
$ scp -P 2222 /mnt/c/temp/cpptools-linux-aarch64.vsix pi@127.0.0.1:~/Downloads
pi@127.0.0.1's password:
cpptools-linux-aarch64.vsix                                                           100%   23MB  96.8KB/s   04:00
```

拡張機能をオフラインでインストールする方法ですが、下記サイトにVSCodeの図があります。

https://stackoverflow.com/questions/37071388/how-can-i-install-visual-studio-code-extensions-offline

リモート側のVSCodeの「拡張機能」メニューの「…」の「VSIXからのインストール…」から「cpptools-linux-aarch64.vsix」ファイルを選択してインストールしました。これもネットワークが不安定なので何度か繰り返しています。
よくやく環境が整って、デバッグできるようになりました。

![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L2を使用すればいいです。
WSLでは画面に何か表示されるまで数分待つ必要がありましたが、WSL2ではすぐに何か表示されるようになっています。
また、WSLgが標準で使用できるようになるので、設定などが不要でGUIアプリが使えるのはいいですね。

VS Codeが悪いと思うのですが、ネットワークが不安定なのが気になっています。今後改善されることを期待しています。