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

# はじめに
お仕事でRasberry Pi用のインターフェイスプログラムを作成がありました。もともとWindows用にDelphi5からC#（.NET 4.x）で移植したものがあり、Linux用でも動作するためC#（.NET 5.0） に修正してRasberry Piでも動作することを確認できました。
Rasberry Pi 4自体は専用箱に格納されており、アプリケーションもUSBメモリに格納した状態で動作する方針なのでイジりにくい状態です。そこで、仮想環境があればいろいろと試せるかなと思って調べ始めました。

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

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

※2020年5月にLinuxベースの公式OSの名称を「Raspbian」から「Raspberry Pi OS」に変更した。

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

[QEMU公式サイト](https://www.qemu.org/)からDOWNLOAD-Windowsと辿り32bitもしくは64bitのリンクをクリックします。
画像付きのインストールは下記サイトを参照、自分は標準の「C:\Program Files\qemu」にインストールしました。
[オープンソースの仮想化機能QEMU for Windowsのインストール方法](https://itneko.blogspot.com/2020/06/qemu-for-windows.html)

## QEMU用カーネルなどをダウンロード
https://github.com/dhruvvyas90/qemu-rpi-kernel よりQEMU用カーネルをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/16412016-820a-0c58-6867-a31bb1a5d2aa.png)

qemu-rpi-kernel-master.zipファイルを展開、kernel-qemu-4.19.50-busterとversatile-pb-buster.dtbのみ使用します。
Raspberry Pi OSのベースであるDebianのコードネームは、wheezy → jessie → stretch → buster の順で新しい。最新版は busterになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/868e286d-f1cf-3986-f743-cbebe0f3c0e2.png)

1つ目は実際のカーネルイメージで、2つ目はデバイス ツリーblobになります。
Raspberry Piボード上のシステムで使用可能なハードウェアを記述するために、DTS(デバイス ツリー ソース)ファイルが使用されます。これらのファイルのコンパイル済みバージョンはDTBと呼ばれ、拡張子が.dtbのファイルになります。

## イメージファイルのダウンロード
CPU別(armhf[^1],arm64[^２]など)にイメージファイルには3種類用意されています。

[^1]: armhf…ARMというCPUアーキテクチャ上で動かす、浮動小数点数命令を使うバージョン。Raspberry Piなどがこちらを使います。
[^２]: amd64…x86を64ビットに拡張したx64対応のもの。政治的な事情もあってこの命令セットのCPUをAMDが先に出したため、Intelのx64でもamd64版となります。ほとんどのパソコンはこちらです。

* Raspberry Pi OS 軽量版(lite)
* Raspberry Pi OS デスクトップ(Desktop)
* デスクトップと追加パッケージを備えた Raspberry Pi OS(full)

日本からなら北陸先端大にあるミラーサーバーからの方が速くダウンロードできる。
http://ftp.jaist.ac.jp/pub/raspberrypi/

今回は、Raspberry Pi OS デスクトップのarmhfの現時点(執筆時2021/06/07)の最新版を辿ってZIPファイルをダウンロードします。
例 2021-05-07-raspios-buster-armhf.zip
http://ftp.jaist.ac.jp/pub/raspberrypi/raspios_armhf/images/

2021-05-07-raspios-buster-armhf.zipファイルを展開、2021-05-07-raspios-buster-armhf.imgを使用します。

## 対象フォルダに格納
自分の場合、Cドライブ直下に「RaspberryPi」フォルダを作成して、3つのファイルを格納しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/17d1ac2a-6602-1d30-0b6f-224531ccabf5.png)

# 初回起動
C:¥RaspberryPiフォルダに下記の「run.bat」を作成します。
run.batをダブルクリックして、数分すれば Raspberry Pi OSが起動します。

```bat:run.bat
@echo off

cd /d %~dp0

"C:\Program Files\qemu\qemu-system-arm.exe" -M versatilepb ^
-cpu arm1176 ^
-m 256 ^
-drive format=raw,file=2021-05-07-raspios-buster-armhf.img ^
-net nic ^
-net user,hostfwd=tcp::2222-:22 ^
-dtb versatile-pb-buster.dtb ^
-kernel kernel-qemu-4.19.50-buster ^
-append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" ^
-no-reboot
```

※コマンドラインにて、ハット(^)記号を使用するとコマンドを複数行に分けて記述することができます。改行後は「More?」と表示されますが、問題なく実行できます。**ハット(^)記号を削って１行にしてしまっても構いません。**

※画面上に「vpb_sic_write: Bad register offset 0x2c」が出るが気にしない。

赤文字のFAILDが数個出てくるが、問題ない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/ca55a0dd-54d3-1040-f4da-846b1e112fdb.png)

## QEMUエミュレータ
|エミュレータ|Raspberry Piモデル|
|:--|:--|
|qemu-system-arm|RaspberryPi 2向けのARM1176|
|qemu-system-aarch64|RaspberryPi 2、3向けのCortex-A53|

## QEMUオプション
[QEMUオプション](https://wiki.gentoo.org/wiki/QEMU/Options)

主なQEMU起動時のオプションについての説明をまとめておきます。

### -M マシン名
エミュレートするマシン名を指定します。
多くのチュートリアルでは、versatilepbマシンを使用しています。
versatilepbは正式には「ARM Versatile/PB (ARM926EJ-S)」で ARM Versatile Platform Baseboard for ARM926EJ-S という開発用ボードのようです。

下記サイトでマシン一覧を見ることができますが、raspi2がないなど情報が古いですね。
https://wiki.qemu.org/Documentation/Platforms/ARM

最新情報は、次のコマンドで一覧が表示できます。

```
qemu-system-arm -M help
or
qemu-system-aarch64 -M help
```

マシンの中には、raspi2(Raspberry Pi 2)があるのですが、~~これはネットワークやキーボードとマウス用の USB をサポートしていないなど、欠点があるので、チュートリアルではあまり使用されてないようです。~~

ARM64(qemu-system-aarch64)であればマシンの中に、raspi3(Raspberry Pi 3)があり、幾つかのチュートリアルが散見されます。ただデスクトップ画面が使用できるのかは未確認です。

【2021/06/16追記】
QEMU 5.1以降でUSBコントローラをサポートしたことでネットワーク等が使用できるようになったとのこと。マシンをraspi2にして動作しているチュートリアルを見つけました。試して、別途記事にします。

### -m メモリ数
RAMの容量を指定します。
versatilepbマシンを指定した場合は最大256MiBで、それ以上を指定するとエラー「qemu-system-arm.exe: versatilepb: memory size must not exceed 256MB」になります。

マシンによってRAMの最大制限が変わります。その為、raspi3マシンを指定した場合には 1Gを指定することが可能です。

### -cpu CPUの種類
エミュレートするCPUの種類を指定します。

最新情報は、次のコマンドで一覧が表示できます。

```
qemu-system-arm -cpu help
or
qemu-system-aarch64 -cpu help
```

今回はarm1176を指定している。
Raspberry Pi は Broadcom BCM2835 を搭載しており、このアプリケーションプロセッサは ARM1176JZ-F となっています。

## マウス操作
### QEMUを抜ける
マウスカーソルがラズパイの画面に持っていかれるので、抜けるにはQEMUウィンドウのタイトルバー「QEMU-Press Ctrl + Alt + G release grab」に記載されているように、「Ctrl + Alt + G」を同時に押します。

### 位置が合わない
マウスカーソルが妙なところを指して位置が合わない場合、QEMUウィンドウを最大化するとマウスカーソルの位置が合います。

## 初期設定画面
初期設定画面では国の設定以外は Nextボタンをクリック(パスワード変更なども)、アップグレードは空き容量が足りないのでSkipボタンをクリックして最終的にDoneボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/eba73943-4504-b0b6-11e2-b0b377ebc266.png)

空き容量が263.8 MiBしかありません。後述する方法で空き容量を増やすことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/154c19c9-0c80-cb10-d06c-cb2150033df2.png)

空き容量を増やしたいので、QEMUウィンドウのバツボタンなどでQEMUを一旦終了させます。

# 空き容量を増やす
空き容量を増やすには、最初にイメージファイルのリサイズを行い、次にパーティションのリサイズを行います。

## イメージファイルのリサイズ
以下のコマンドでイメージのサイズ変更を行います。
ここでは2GB分拡張していますが、拡張するサイズを変更するは `+2G` の箇所を適宜変更してください。

```txt
"C:\Program Files\qemu\qemu-img.exe" resize 2021-05-07-raspios-buster-armhf.img +2G
WARNING: Image format was not specified for '2021-05-07-raspios-buster-armhf.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.
```

C:¥RaspberryPiフォルダの「run.bat」をダブルクリックして、Raspberry Pi OSを再度起動します。

## パーティションのリサイズ
Raspberry Pi OS上のターミナル画面からディスクユーティリティーをインストールします。
インストール後に`gnome-disks`でディスクユーティリティーを起動させます。

```bash
$ sudo apt install -y gnome-disk-utility
$ gnome-disks
```

ディスクユーティリティー画面にて、パーティション2を選択して設定アイコンのメニューから「Resize」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/50091892-7c6e-ce66-50cd-aabe4ac00271.png)

パーティションサイズを最大まで延ばして、「Resize」ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/d6a2e3b1-c1c7-fcc0-e1dc-af43be580a21.png)

認証画面が出てくるので、パスワードを入力します。
デフォルトの管理者 ユーザー名:pi パスワード:raspberry

これで空き容量を増えました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/24ded698-8f4b-f432-358d-da7aa4557c91.png)

# スワップ領域増加
スワップ領域も少ないので下記コマンドで修正を行います。
初心者にも比較的使いやすい nanoテキストエディターを使用します。

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

#CONF_SWAPSIZE=100
CONF_SWAPSIZE=1024
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/6ae4f9a2-3487-6457-9a3e-beca83e02c9c.png)

保存をして閉じたら下記コマンドでスワップファイルサイズの更新を行います。

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/180e8fe5-8f6c-0c8d-3f78-0ffe56327f44.png)

# アップデート
空き容量を増えたので、アップデートしておきます。

```bash
$ sudo apt update
```

# その他
## SSH
スタートボタンメニューから「設定」の「Raspberry Pi設定」をクリックします。
Raspberry Pi設定画面のインターフェイスタブにて、SSHとついでにVNCを有効にして「OK」ボタンをクリックします。
※後述していますが最終的にVNCは無効にしています。
設定後に再起動確認画面が出てくるので「はい」ボタンをクリックします。
[Raspberry Pi 4にSSHとVNCで接続してみた](https://dev.classmethod.jp/articles/raspberry-pi-4-ssh-vnc-remote/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/d4705688-5637-8c2d-76f4-70ff3c5327cf.png)

C:¥RaspberryPiフォルダの「run.bat」をダブルクリックして、Raspberry Pi OSを再度起動します。

Raspberry Pi OS上のターミナル画面から、「hostname -i」でホスト名のipアドレスを確認できます。

```bash
# ホスト名のipアドレスを表示
$ hostname -i
127.0.0.1
```

Windows 10では標準でSSHクライアントが使用できます。今回は、Windows Terminal(PowerShell)でSSHに接続します。
Raspberry Piのホスト名が「127.0.0.1」になっているので、下記を入力します。

```
SSH pi@127.0.0.1 -p 2222

パスワード入力 raspberry
```

Raspberry Pi OS上に接続できたので、lsb_releaseコマンドでバージョンを確認してみます。

```bash
pi@raspberrypi ~ $ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:        10
Codename:       buster
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/d2f99202-01d3-e5c9-2390-e25edd683715.png)

## VNC
Raspberry Pi OSのタスクバーのVNCアイコンにバツマークが付きます。
"vnc server is not license"となっており、ライセンスがないとのことで、最終的には、VNCは無効にしました。

## Web Browser
Web Browserのアイコンをクリックしても、何も画面に出ないまま終了します。
そこで、ターミナル画面で「chromium-browser」とすると下記のエラーがでます。

```bash
$ chromium-browser
FATAL:zygote_host_impl_linux.cc(117)] No usable sandbox! Update your kernel or see https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md for more information on developing with the SUID sandbox. If you want to live dangerously and need an immediate workaround, you can try using --no-sandbox.
パスエラー
```
you can try using --no-sandbox とオプション「--no-sandbox」を付けてトライしてみる。

```bash
$ chromium-browser　--no-sandbox
```

メモリが256MBしかないため、ものすごく重たい(Yahooが表示されるまで５分以上かかる)ですが、Web画面が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/4b2ff260-3100-2ce9-fe8d-ae323e64e9c9.png)


## VSCode
Raspberry Piのクロスコンパイルをしたかったので、一番インストールしたいアプリケーションであった。

```bash
$ sudo apt install code
```

インストールは出来たものの、メニューからVSCodeをクリックしても何も画面に出ないまま終了します。そこで、ターミナル画面で「code」とするとエラー「Illegal instruction」となっていました。
一旦、アンインストールしてWindows 10からVSCode上でRemort SSHから接続するとリモート先にVSCodeが自動でインストールされるのですが、その時にエラー「Unsupported architecture: armv6l」が出ていました。

VSCodeがサポートしているのは、CPUのアーキテクチャが`armv7l`のRaspberry Piです。つまり、Raspberry Pi 2系統とRaspberry Pi 3系統はすべて実行可能ですが、Raspberry Pi初代やRaspberry Pi Zero系統はCPUのアーキテクチャが`armv6`となっているので現在は実行不可能です。

エミュレートするマシンが`versatilepb`　ではなく、`raspi3`で動作するようになれば、VSCodeも動作するかと思います。

VSCodeではクロスコンパイルを実現できませんでしたが、Visual Studio 2019の​[C++ による Linux 開発] ワークロードを使用することで、エミュレーター環境でクロスコンパイルを実現できました。これは別途、記事を書きます。
参照：[C++ を使用した Linux の開発 | Linux 用アプリケーションの作成とデバッグ](https://docs.microsoft.com/ja-jp/cpp/linux/?view=msvc-160)

# 最後に
Raspberry Piのお仕事とはいえ、.NET 5で開発したものがあっさり動作したので仮想環境を構築するのはオマケで仕事外で趣味の領域です。今回の仮想環境を構築で QEMUというのを知ったし、Linuxのクロスコンパイルの方法も分かった。
Windows開発に慣れてしまっているのでGUI環境があると安心するが、慣れてくればCUI環境のみの Raspberry Pi OS 軽量版(lite)を使用すればいいかも知れない。

Windows10上で動作したので、次はMac(Intel)で動作する記事を書いていきます。Macで動作するのはすでに確認済み。
あとは、エミュレートするマシンを`versatilepb`ではなく、`raspi２`や`raspi3`(Raspberry Pi OS 64-bit)としていろいろ試してみたいですね。

【2021/06/17追記】 Mac版の記事を書きました。

https://qiita.com/yaju/items/9bb341c1b222590a92ba

【2021/07/04追記】 raspi２とraspi3マシンの記事を書きました。

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

# 参考
* [Raspbian Stretch 2018/3/13版をQEMUで動かす](https://qiita.com/Nebutan/items/1cffada81e61a9f2ed58)
* [Raspbian Jessie 2017/7/5版をQEMUで動かす](https://qiita.com/Nebutan/items/577dd7890f0d7a52d4a0)
* ["Ubuntu で" Raspberry Pi を動かす QEMU](https://qiita.com/mugimugi/items/eaf3721a50dc618c07ac)
* [How to run the Raspberry Pi Os in a virtual machine with Qemu and Kvm](https://linuxconfig.org/how-to-run-the-raspberry-pi-os-in-a-virtual-machine-with-qemu-and-kvm)
* [Windows で Raspbian システムを起動（QEMU, qemu-rpi-kernel を使用）](https://www.kkaneko.jp/tools/container/windows_qemu.html)
* [QEMU on M1 Mac](https://qiita.com/hjmr/items/abeb9a4567d08ddcc3b9)
* [RaspberryPi向けLinuxをQEMUでエミュレートする](https://www.usagi1975.com/29mar172033/)
* [QEMU on WindowsでネイティブのRaspberry Pi OS (64-bit) を動かす](https://blog.k-san.info/raspios-arm64-on-qemu-on-win)
* [Windows上でRaspberry Piのエミュレータを動かしてみたり](http://blawat2015.no-ip.com/~mieki256/diary/201711031.html)