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

# はじめに
前記事ではWindows10上で構築しましたが、今回はIntel Mac上で構築します。

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

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

# 環境
* Mac Book Pro(2.3 GHz 8コアIntel Core i9) Big Sur 11.3
* QEMU 6.0

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

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

```zsh
% brew install qemu
```

### Homebrewのインストール
自分の場合、Homebrew 自体がインストールされていなかったので下記の方法でHomebrew をインストールしました。

```zsh
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

% brew -v          
Homebrew 3.1.9
```

### wgetのインストール
wgetもインストールされていなかったので、インストールしました。

```zsh
% brew install wget
```

## 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/edac0203-f044-adda-60ce-6baf55241950.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を使用します。

## 対象フォルダに格納
自分の場合、home直下に「RaspberryPi」フォルダを作成して、3つのファイルを格納しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/22131432-b01c-1aa7-ffd5-c360d9da1e84.png)


# 初回起動
~/RaspberryPiフォルダに下記の「run.sh」を作成します。

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

qemu-system-arm \
-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
```

ターミナル上でrun.shに実行権限を追加してから実行すれば、 数分でRaspberry Pi OSが起動します。

```bash
% chmod 755 ~/RaspberryPi/run.sh
% ~/RaspberryPi/run.sh
```

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

赤文字のFAILDが数個出てくるが、問題ない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/4639e6a3-d7bb-624d-95ef-f426de4ae474.png)

## QEMUエミュレータ
|エミュレータ|Raspberry Piモデル|
|:--|:--|
|qemu-system-arm|RaspberryPi 1、Zero向けの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 をサポートしていないなど、欠点があるので、チュートリアルではあまり使用されてないようです。~~ 
QEMU 5.1以降でUSBコントローラをサポートしたことでネットワーク等が使用できるようになったとのこと。raspi2でも試してみたいですね。

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

### -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」を同時に押します。

### 位置が合わない
Windows10ではマウスカーソルが妙なところを指して位置が合わない場合、QEMUウィンドウを最大化するとマウスカーソルの位置が合いました。
Macでは、今のところ位置が合わないということは発生していません。

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

空き容量が263.8 MiBしかありません。後述する方法で空き容量を増やすことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/2281059d-ceb7-d737-3687-82323a0b8756.png)

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

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

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

```txt
% qemu-img resize RaspberryPi/2021-05-07-raspios-buster-armhf.img +2G
WARNING: Image format was not specified for 'RaspberryPi/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.
```

ターミナル上で「run.sh」を実行して、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)

ターミナル上で「run.sh」を実行して、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/961c3d48-9658-9323-7841-0e804760cf19.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」となっていました。
一旦、アンインストールしてMacから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ではクロスコンパイルを実現できませんでしたが、Windows10ではVisual Studio 2019の​[C++ による Linux 開発] ワークロードを使用することで、エミュレーター環境でクロスコンパイルを実現できました。
参照：[C++ を使用した Linux の開発 | Linux 用アプリケーションの作成とデバッグ](https://docs.microsoft.com/ja-jp/cpp/linux/?view=msvc-160)

MacだとVisual Studio for MacはC++に対応していなかったので、Xcodeとか使用すれば出来るのではないでしょうか。

# 最後に
最初に「ラズパイ MAC QEMU」で検索した下記のトップ記事を参考に構築したのですが、GUI環境ができない。

https://qiita.com/karaage0703/items/366eb17906a3341f1999

他のサイトでもCUI環境のみ(後で分かったけど、-nographicオプションとイメージはliteを使用していた)

https://docs.j7k6.org/emulate-raspbian-buster-qemu-macos/

その後、Windows 10でいろいろやってみたらGUI環境が構築できたんですよね。MacでもGUI環境が構築できるのかもと、もう少し調べて下記サイトでGUI環境が構築できるのを確信したので、パラメーターを見直したところ無事にMacでもGUI環境が構築できました。

https://joshondesign.com/2021/04/15/emu_pi_mac

この次はエミュレートするマシンを`versatilepb`ではなく、`raspi3`(Raspberry Pi OS 64-bit)としていろいろ試してみたいですね。

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

https://qiita.com/yaju/items/36ecee632d2eeee38d63

# 参考
* [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)