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

# はじめに
前記事ではRaspi2、Raspi3マシンをLinux上で構築しましたが、今回はWindows10上で構築します。

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

初代RaspberryPi用のversatilepbマシンの記事は下記になります。

https://qiita.com/yaju/items/4bf9e39416e0cb1bdaa9

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

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

## イメージファイルのダウンロード
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/

### 使用するイメージファイル
* Raspi2マシン用に「[2021-05-07-raspios-buster-armhf](http://ftp.jaist.ac.jp/pub/raspberrypi/raspios_armhf/images/raspios_armhf-2021-05-28/)」
* Raspi3マシン用に「[2020-08-20-raspios-buster-arm64](http://ftp.jaist.ac.jp/pub/raspberrypi/raspios_arm64/images/raspios_arm64-2020-08-24/)」

※Raspi3マシン用(qemu-system-aarch64)では「2021-03-04-raspios-buster-arm64.img」と「2021-05-07-raspios-buster-arm64.img」を使用すると何も起こらない、メッセージ表示すら出ない状態になります。
※Raspi2マシン用で画面が起動するがマウスが動作しない場合、「2020-08-20-raspios-buster-armhf」にするといいでしょう。

# Raspi2マシン
## フォルダ作成
Cドライブ直下に「RaspberryPi2」フォルダを作成します。
ダウンロードした「2021-05-07-raspios-buster-armhf.zip」を「RaspberryPi2」フォルダに展開します。

## カーネルとデバイスツリーソースファイルの抽出
イメージファイル内から「kernel7.img」と「bcm2709-rpi-2-b.dtb」を抽出します。

Macでは、イメージファイルをマウント出来てファイルを抽出できますが、Windowsではマウントしようとしても「ディスク イメージ ファイルが壊れています。」となってしまいます。
WSL上ならマウント出来るかと思ったのですが、ループバックデバイス(losetup)をサポートしていませんでした。
※Raspi3マシンのとこに記載したが、WSL2ならループバックデバイス(losetup)をサポートしています。
Macがない場合、VirtualBox上にUbuntuをインストールしてファイルを抽出することになります。
[Linux上でカーネルとデバイスツリーソースファイルの抽出](https://qiita.com/yaju/items/edf548efd18f0eaab94a#%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E3%81%A8%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%83%84%E3%83%AA%E3%83%BC%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%8A%BD%E5%87%BA)

RaspberryPi2フォルダには3ファイルがある状態にします。

* 2021-05-07-raspios-buster-armhf.img
* kernel7.img
* bcm2709-rpi-2-b.dtb

### guestfishコマンドによる抽出
下記サイトでは、guestfishコマンドを使用してイメージファイル内から抽出しています。

https://blog.k-san.info/raspios-arm64-on-qemu-on-win

```bash
$ sudo apt update
$ sudo apt install libguestfs-tools -y
$ sudo guestfish --ro -a /mnt/c/RaspberryPi2/2021-05-07-raspios-buster-armhf.img
```

WSL2上で実行してみたのですが、自分の場合エラーで出来ませんでした。

```
><fs> run
libguestfs: error: /usr/bin/supermin exited with error status 1.
To see full error messages you may need to enable debugging.
Do:
  export LIBGUESTFS_DEBUG=1 LIBGUESTFS_TRACE=1
and run the command again.  For further information, read:
  http://libguestfs.org/guestfs-faq.1.html#debugging-libguestfs
You can also run 'libguestfs-test-tool' and post the *complete* output
into a bug report or message to the libguestfs mailing list.
```

## イメージファイルのリサイズ
実行する際のイメージファイルは2のべき乗になっている必要があります。そうしないと下記エラーになります。
「Invalid SD card size: 3.71 GiB
SD card size has to be a power of 2, e.g. 4 GiB.
You can resize disk images with 'qemu-img resize <imagefile> <new-size>'
(note that this will lose data if you make the image smaller than it currently is).」

```txt
"C:\Program Files\qemu\qemu-img.exe" resize 2021-05-07-raspios-buster-armhf.img 8G

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

## 初回起動
RaspberryPi2フォルダに下記の「run.bat」を作成します。
※raspi2マシンの場合、qemu-system-aarch64でも動作します。
2021/07/06 appendオプションに画面サイズを追記

```bat:run.bat
@echo off

cd /d %~dp0

"C:\Program Files\qemu\qemu-system-arm.exe" ^
-m 1024 ^
-M raspi2 ^
-kernel kernel7.img ^
-dtb bcm2709-rpi-2-b.dtb ^
-drive format=raw,file=2021-05-07-raspios-buster-armhf.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
```

# Raspi3マシン
## フォルダ作成
Cドライブ直下に「RaspberryPi3」フォルダを作成します。
ダウンロードした「2020-08-20-raspios-buster-arm64.zip」を「RaspberryPi3」フォルダに展開します。

## カーネルとデバイスツリーソースファイルの抽出
イメージファイル内から「kernel8.img」と「bcm2710-rpi-3-b.dtb」を抽出します。

Macでは、イメージファイルをマウント出来てファイルを抽出できますが、Windowsではマウントしようとしても「ディスク イメージ ファイルが壊れています。」となってしまいます。
WSL上ならマウント出来るかと思ったのですが、ループバックデバイス(losetup)をサポートしていませんでした。
Macがない場合、VirtualBox上にUbuntuをインストールしてファイルを抽出することになります。
[Linux上でカーネルとデバイスツリーソースファイルの抽出](https://qiita.com/yaju/items/edf548efd18f0eaab94a#%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E3%81%A8%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%83%84%E3%83%AA%E3%83%BC%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%8A%BD%E5%87%BA-1)

【2021/11/25追記】
WSL2ではループバックデバイス(losetup)をサポートしています。

https://qiita.com/yaju/items/bb91ea2bf84aac92243c#%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E3%81%A8%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%83%84%E3%83%AA%E3%83%BC%E3%82%BD%E3%83%BC%E3%82%B9%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E6%8A%BD%E5%87%BA

RaspberryPi3フォルダには3ファイルがある状態にします。

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

## イメージファイルのリサイズ
実行する際のイメージファイルは2のべき乗になっている必要があります。そうしないと下記エラーになります。
「Invalid SD card size: 3.52 GiB
SD card size has to be a power of 2, e.g. 4 GiB.
You can resize disk images with 'qemu-img resize <imagefile> <new-size>'
(note that this will lose data if you make the image smaller than it currently is).」

```txt
"C:\Program Files\qemu\qemu-img.exe" resize 2020-08-20-raspios-buster-arm64.img 8G

WARNING: Image format was not specified for '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.bat」を作成します。
2021/07/06 appendオプションに画面サイズを追記

```bat:run.bat
@echo off
 
cd /d %~dp0
 
"C:\Program Files\qemu\qemu-system-aarch64.exe" ^
-m 1024 ^
-M raspi3 ^
-kernel kernel8.img ^
-dtb bcm2710-rpi-3-b.dtb ^
-drive format=raw,file=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
```

# 共通
ここからは、Raspi2マシンとRaspi3マシン共通となります。

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

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

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

### -M マシン名
エミュレートするマシン名を指定します。
最新情報は、次のコマンドで一覧が表示できます。

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

### -m メモリ数
RAMの容量を指定します。
raspi2マシンとraspi3マシンを指定した場合は最大１GiBで、それ以上を指定するとエラー「Invalid RAM size, should be 1 GiB」になります。

### -append 画面サイズ
【2021/07/06追記】
mt08 さんから[Linux側の記事にコメント](https://qiita.com/yaju/items/edf548efd18f0eaab94a#comment-d6f87290a766f6d1284f)を頂き、appendオプションに画面サイズを指定することで画面サイズを変更することが出来ました。
bcm2708_fb.fbwidth=XXX bcm2708_fb.fbheight=YYY

```text:例
-append "console=ttyAMA0 root=/dev/mmcblk0p2 rw rootwait rootfstype=ext4 dwc_otg.fiq_fsm_enable=0 bcm2708_fb.fbwidth=1280 bcm2708_fb.fbheight=720"
```
しかも、画面サイズ800x480で背景が青系統だったのが、画面サイズ1280x720で背景が本来のオレンジ系統になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/5599818b-abe8-5f95-0367-bd0b9f6b9fb2.png)

## マウス操作
### QEMUを抜ける
マウスカーソルがラズパイの画面に持っていかれた場合、抜けるにはQEMUウィンドウのタイトルバー「QEMU-Press Ctrl + Alt + G release grab」に記載されているように、「Ctrl + Alt + G」を同時に押します。
ここは改善されたのか、ラズパイの画面範囲を超えると自動的に抜けるようになっています。

## 起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/65b4c545-960f-6086-cb86-cd9853a68070.png)
ログインを求められますが、入力しても、しなくても問題ありません。
デフォルトの管理者 ユーザー名:pi パスワード:raspberry

## 初期設定画面
~~背景画像がversatilepbマシン時はオレンジ系統でしたが、今回は青系統になっています。~~

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

# 空き容量を増やす
空き容量が195.1 MiBしかありません。後述する方法で空き容量を2.5GiB(8Gの場合)まで増やすことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/6c896cc5-f8ce-1ec8-eac0-b15129db4959.png)
ターミナルで以下を実行し、ディスクの容量分だけ利用できるようにファイルシステムを拡張する。

```bash
$ sudo raspi-config  --expand-rootfs
```

容量は再起動後に反映されますので、一旦QEMU画面を閉じます。
ターミナル上で「run.bat」を実行して、Raspberry Pi OSを再度起動します。

# スワップ領域増加
スワップ領域も少ないので下記コマンドで修正を行います。
初心者にも比較的使いやすい nanoテキストエディターを使用します。
アンダーバーが入力できないので数値のみを変更する。

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

CONF_SWAPSIZE=2048
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/df41f771-4a02-4447-0ecf-9cf93688e680.png)

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/cbd1a328-3676-7884-eb40-3b14dc76d598.png)

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

```bash
$ sudo apt update
```

# その他
## SSH
スタートボタンメニューから「設定」の「Raspberry Pi設定」をクリックします。
Raspberry Pi設定画面のインターフェイスタブにて、SSHを有効にして「OK」ボタンをクリックします。
設定後に再起動確認画面が出てくるので「はい」ボタンをクリックします。
[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/32c99173-2e33-c18f-09d7-715d3963cf6c.png)

ターミナル上で「run.bat」を実行して、Raspberry Pi OSを再度起動します。

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

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

ターミナルをもう一つ起動して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/42808ec6-0354-e1f0-990f-7cb2f85f6571.png)
sshコマンド時に「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」が出たら下記サイトを参考に対応して下さい。
[SSH接続時にエラー](https://qiita.com/hanlio/items/179add527421c3b7839c)

## Web Browser
Web Browserのアイコンをクリックすれば、数分かかりますがブラウザが起動します。
**※Raspi2では起動しようとすると、QEMUごと落ちてしまう。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/0c252b7f-d98b-cb6b-1d68-56a50a693eb9.png)

## VSCode
Raspberry Piのクロスコンパイルをしたかったので、一番インストールしたいアプリケーションであった。
**※Raspi2では起動しようとすると、QEMUごと落ちてしまう。**

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

インストールが完了するまで時間がかなりかかります。
スリープするとネットワークまで停止するので、一時的にスリープを解除しておくといいでしょう。

インストールが完了するとメニューのプログラミング配下に「Visual Studio Code」が追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/06c40b9d-c87d-997f-306c-604f1b98b290.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/dff2d789-4bfe-3722-db5c-894b131a7d00.png)
動きますが、ものすごく重たいです。また、C++とかコンポーネントのダウンロード中で進まない状態など使用するには難あり。
親側のWindows10にもVisual Studio Codeをインストールして、「Remort SSH」で動くことを期待したのですが、残念ながらリモート側にVSCodeをインストールしようとしてエラーになってしまいます。
「** Note: Support for architecture "aarch64" is in preview **」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/9924760f-9edd-b4c3-aa81-bc6b35e09d90.png)

【2021/07/06追記】
Windows10のVSCodeからリモートホスト側のLinuxのQEMUに対して、Remort-SSHしたら動作しました。組み合わせみたいなのがあるのだろうか、引き続き調査してみます。

【2021/07/20追記】
リモート側とリモートホスト側がWindowsという組み合わせでは「vscode-server」はインストールできたのだが、その後の接続が安定しないので、WSLを使用する方法にしてみました。

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

# 不満点
* アンダーバーとパイプがキーボードと円マークで入力できない
* ~~画面サイズが変更できない~~
* Visual Studio CodeでRemort SSHが動作しない

画面サイズは、Raspberry Pi設定にあるDisplayタブの解像度の設定はDefaltしか存在しない。下記サイトを参考に「/boot/config.txt」の設定を変更してみたのですが何も変わりませんでした。
[RaspberryPiの解像度が変えられない時の対処法](https://www.mechatronahibi.com/raspi-disp-resolution-config/)

## キー入力の調査結果
【2021/07/08追記】
versatilepbマシンではアンダーバーとパイプと円マークは入力できるので、`xev`でキーコードを調べるとKeyCodeは97(underscore)と132(yen bar)でした。Raspi2、Raspi3マシンで`xev`でキーコードを調べようとしても反応しないのです。
つまり、キースキャンができないのでXmodmapでKeyCode 97と132に割り当てしても反応しない。
そのため、空いているところに(例 シフト+スペースキーにアンダーバー)割り当てることなら可能です。

# 最後に
Linuxで動作することができたので、Windowsでも試してみると同様に動作させることが出来ました。
Linuxと違いRaspi2マシンだとWebブラウザとVSCodeがQEMUごと落ちてしまいます。「qemu-system-arm」から「qemu-system-aarch64」に変更しても同じでした。
Windowsでは、イメージファイルをマウントできないのが残念です。せめてWSLならマウントできるようになっているのを期待したんですがサポートしてないんですよね。今後に期待です。guestfishコマンドが使えそうだったんだけど、あと一歩かな。

今回の件でネットでかなり検索しましたが、raspi2マシンとraspi３マシンで画面まで表示しているサイトはありませんでした。需要がないのか、SSHのみならlite版で済ますからそこまでやらないのかって感じですかね。


不満点のキーボードと~~画面サイズ~~の件が分かる方がいたらコメントを頂けると嬉しいです。

# 参考
* [How to emulate Raspios natively in QEMU](https://peterbabic.dev/blog/how-emulate-raspios-natively-qemu/)
* [Emulate RaspberryPi 2 on Ubuntu 20.04 using qemu](https://lynxbee.com/emulate-raspberrypi-2-on-ubuntu-20-04-using-qemu/)
* [QEMUとRaspberry PI - 山の上のブログ](http://www.yamanoue.atnifty.com/2020/08/qemuraspberry-pi.html)
* [QEMU on WindowsでネイティブのRaspberry Pi OS (64-bit) を動かす](https://blog.k-san.info/raspios-arm64-on-qemu-on-win)
* [QEMU on M1 Mac](https://qiita.com/hjmr/items/abeb9a4567d08ddcc3b9)
* [arm raspi2/raspi3 emulation has no USB support](https://bugs.launchpad.net/qemu/+bug/1772165)