ChromeOS Flexを仮想マシンで動かす

# はじめに

[ChromeOS](https://www.google.com/intl/ja_jp/chromebook/chrome-os/) は、Chromebookと認定されたハードウェア向けにGoogleがリリースしているOS商品です。

[ChromiumOS](https://www.chromium.org/chromium-os/) は、ChromeOSの元となったソースコードをOSSとして公開したものです。  

[ChromeOS Flex](https://chromeenterprise.google/intl/ja_jp/os/chromeosflex/) は、もともとはCloud ReadyというNeverware社の製品で、PC向けにChromiumOSから派生したOSでした。その後、Googleが買収し、ChromeOS Flexとなりました。

ChromeOS Flexを実PCにインストールするには [Googleの公式ページ](https://chromeenterprise.google/intl/ja_jp/os/chromeosflex/)  に書いてあるとおりにすればいいのですが、仮想マシンで動かそうとするとVirtualBoxやVMWareをサポートしていないため、なかなか動かすことができません。この記事ではChromeFlexを、Linux上のQEMU/KVMで動作させる方法を解説します。

# 環境

この記事では、以下の環境で動作確認してあります。

- ホストOS: Fedora39
- QEMU: 8.1.3
- ChromeOS Flex: 122

# ChromeOS Flexのリカバリイメージを用意する

まずChromeOSのリカバリイメージを、 Chromium Dashからダウンロードします。

https://chromiumdash.appspot.com/serving-builds?deviceCategory=ChromeOS%20Flex

「Recovery Images」の列から番号の一番大きいものをダウンロードします。ダウンロードが終わったらzipを解凍しておきます。

# ChromeOS Flexのインストール

ChromeOS FlexのVM起動用の chromeoslauncher というシェルスクリプトを作成しました。こちらをベースに進めます。

https://raw.githubusercontent.com/yas99en/chromeoslauncher/main/chromeoslauncher

リカバリーイメージを指定して、VMを立ち上げます。初回起動時にインストール先の仮想HDDイメージも作成されます。

```
$ chromeoslauncher -r chromeos_15753.46.0_reven_recovery_stable-channel_mp-v3.bin
```
しばらくするとChromeOSの画面が表示されます。言語とキーボードを選択したら画面に従ってChromeOS Flexをインストールしてください



<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/f6cd2b73-490c-7b1d-a67e-a34732cb7dc7.png">

インストールが終わったら、OSを終了させます。


<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/d89773f6-accd-994b-a779-3302c6b2e030.png">

# ChromeOS Flexの起動

ChromeOS Flexを起動させるためにchromeoslauncherを引数なしで実行します。

```
$ chromeoslauncher
```

OSが立ち上がるとセットアップが始まります。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/a8c56fd5-adde-d2b1-3368-c9ff31f2a711.png">

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/f0ace871-0df4-6b3b-da1b-d7489f7b6540.png">

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/5910692d-d989-a6af-c767-019e47e0ea20.png">

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/55022855-a53a-a9bc-92c8-91303211cf74.png">


これでChromeOS Flexのホーム画面が表示されます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/c4e9aaaa-da53-30d2-9a24-355b8c9a49b3.png">

電源の設定で、スリープに入らないよう設定しておいた方がいいでしょう。


<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/aa8a52c6-bcf8-35fa-514b-62b25f70706a.png">

# chromeoslauncher について

chromeoslauncherは初回起動時に、 `$HOME/vm/qemu/chromeos` に以下のファイルを作成します。末尾のchromeosの部分は `-n name` のように指定することで変更できます。

```
$ ls ~/vm/qemu/chromeos/
OVMF_VARS.fd  image.qcow2
```
- OVMF_VARS.fd: EFIのパラメータを格納します
- image.qcow2: ChromeOS FlexをインストールするHDDイメージです。 サイズは50GBです

chromeoslauncherは以下のように仮想マシンを起動します。

```
qemu-system-x86_64 \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE.fd \
-drive if=pflash,format=raw,file=$HOME/vm/qemu/chromeos/OVMF_VARS.fd \
-display sdl,show-cursor=on,gl=on \
-device virtio-vga-gl,xres=1280,yres=800 \
-usb -device usb-tablet \
-drive format=qcow2,file=$HOME/vm/qemu/chromeos/image.qcow2 \
-m 4G \
-enable-kvm \
-smp 2 \
-audiodev sdl,id=audio0 \
-device intel-hda \
-device hda-output,audiodev=audio0 \
-cpu host
```

usb-tabletを指定してあるのは、デフォルトではマウスをうまく扱えないためで、タブレットモードで起動しています。このためマウスのホイールや右クリックは使用できません（残念ながら端末で文字列をコピーしても、ペーストできません）。

いくつかのパラメータは `$HOME/.chromeoslauncher` で指定することができます。

※ QEMU/KVMには、virt-managerというGUIフロントエンドがあります。virt-managerでもchromeoslauncherと同様なことはできますが、残念ながらウインドウサイズの変更に追随して、ChromeOS Flex側の解像度を変更するようにはできませんでした。

# WSL2やVirtualBoxでの使用

WindowsのWSL2や、VirtualBoxなどの仮想マシン上では、chromeoslauncherは3Dアクセラレーションの関係でうまく動かないかもしません。

WSL2のUbuntu22に関しては、下記ページのOption2に従ってMesaの最新版を入れれば、多少動作は不安定ですが、動きました。

- [D3D12 GPU Video acceleration in the Windows Subsystem for Linux now available!](https://devblogs.microsoft.com/commandline/d3d12-gpu-video-acceleration-in-the-windows-subsystem-for-linux-now-available/)

VirtualBox上のFedoraやUbuntuは、NestedVMと3Dアクセラレーションを有効にしても起動できませんでした。
```
$ chromeoslauncher -3
```
とすると一応動くかもしれません。ただし一つの操作に対して、画面の書き換えに5分ほどかかったりするので、実用レベルではないかもしれません。

- [QEMUでGPUの3Dアクセラレーションを利用する](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0592)





# Linux開発環境（Crostini）

Linux開発環境を利用するには、以下の画面でLinux開発環境をオンにします。
後述の開発者モードは不要です。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/e3532a0d-16f8-a749-4c34-c685745bd0ce.png">

インストールが終わるとLinux開発環境のコンソールが立ち上がります。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/464319e9-6dbd-dfdb-6c76-e3554c45115e.png">


中身はDebianなので、aptなどを使って必要なパッケージをインストールできます。以下のページなどを参考にしてください。

- [Crostiniを日本語で使えるようにするぞ！](https://qiita.com/cyber-yuito723/items/4638bb058f79d14dce91)
- [Chrome OSのLinux環境・crostiniとは何か？](https://chromebooker.net/topics/o25itaauo3/)

# 開発者モード

ChromeOS Flexでは、開発者モードを有効にすると、後述のCroshでshellコマンドなどが使用可能になり、ChromeOS Flex自身をLinux端末として使えるようになります（後述のChromeBrewをインストールしないとLinux端末としてはかなり制限されています）。

開発者モードを有効にするには、カーネルパラメータの追加が必要になるので、Liveイメージで起動して、grub.confを書き換えます。Liveイメージは何でも良いですが、ここでは [GParted](https://gparted.org/) を使用して、以下のように起動します。

```
$ chromeoslauncher -c gparted-live-1.6.0-1-amd64.iso
```
画面の指示に従いGPartedを起動すると、ChromeOS Flexのパーティションマップが表示されます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/23724190-1f50-bf04-284e-0c610497c9e9.png">

端末を起動して作業を進めますが、英語キーマップになっているので、必要に応じて、日本語キーマップに変更します。

```
$ setxkbmap jp
```

パーティションマップからEFI-SYSTEMパーティションを特定したら、
マウントして、grub.cfg を書き換えます。

```
$ sudo mount /dev/sda12 /mnt
$ cd /mnt/efi/boot
$ sudo cp grub.cfg grub.cfg.org
$ sudo sed -i -e 's|noinitrd|noinitrd cros_debug|' grub.cfg
```
書き換えが終わったらOSをシャットダウンして、通常通りChromeOS Flexを起動します。

```
$ chromeoslauncher
```

参考
- [Chrome OS Flexで開発者モードを有効にする](https://yukineko.me/archives/1065)

# Crosh

- croshは、ChromeOS標準のシェル環境で、開発者モードでなくても使用可能です
- Ctrl + Alt + T で起動できます
- crosh自身は、通常のLinuxシェルとは別物で、専用のコマンドのみ使えます
- 開発者モードが有効だと、shellコマンドが使用でき、shellコマンドを実行すると、通常のLinuxシェルが使えるようになります


<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/91dd2c3b-7b84-1b2e-955a-ebcae5492976.png">


参考
- [ChromeOSのcroshコマンド一覧](https://qiita.com/htnk/items/e1f38956f9e8e3d7027b)

# Chromebrew

Chromebrewは、croshで使えるパッケージマネージャーです。これを使うとcroshのshellがLinux端末として十分に使えるようになります。

https://chromebrew.github.io/

https://github.com/chromebrew/chromebrew/wiki

croshでshellコマンドを実行後、以下のコマンドでセットアップできます。

```
$ curl -Ls git.io/vddgY | bash
```

セットアップ後は、例えばvimは以下のようにインストールできます

```
$ crew install vim
```



参考
- [Chromebookに開発環境を実装する方法2 ― Chromebrew編](https://chromesoku.com/chromebrew/)

# Sommelier

Sommelier（ソムリエ）はChromeOSのディスプレイサーバーへのproxyです。Sommelierを立ち上げておくと、ChromeBrewのGUIアプリ（XアプリやWaylandアプリ）を立ち上げることができるようになります。

インストールは以下のように行います。

```
$ crew install sommelier
```
インストールが完了すると以下のようなメッセージが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/e37fcb79-993a-b6bc-2389-ac951b2aa65b.png)

bashを立ち上げ直して、以下のようにsommelierを開始します。

```
$ startsommelier
```

これでGUIアプリを立ち上げる準備ができたので、xtermをインストールして立ち上げます。

```
$ crew install xterm
$ xterm
```

参考
- [Sommelier & X11 Wayland Setup](https://github.com/chromebrew/chromebrew/wiki/Sommelier-&-X11-Wayland-Setup) （公式）
- [ChromebookのLinux環境を整える（Crouton + Ubuntu20.04 + Chromebrew + Sommelier）](https://qiita.com/htnk/items/6458ec6412210406486b)
- [CroutonとChromeBrewでChromebookをLinux機のように使う](https://zenn.dev/kentosho/articles/4bda413dd0ae98924c92)

# Crouton

Croutonは、chrootを使って、ChromeOS上で、UbuntuなどのLinuxディストリビューションを動かす仕組みですが、すでに開発終了してしまったようなので割愛します。

https://github.com/dnschneid/crouton/wiki

# RootFSのRWマウント

ChromeOS上で、/etc/hostsなどを書き換えるにはRoot File Systemをrwモードで再マウントする必要があります。下記のリンクを参考にRootFSのRWマウントを試みましたが、うまくいきませんでした。VM環境ではうまくいかないのかもしれません。

- [Developer mode](https://www.chromium.org/chromium-os/developer-library/guides/device/developer-mode/#making-changes-to-the-filesystem)
- [Chromebook writable root](https://xn--1ca.se/chromebook-writable-root/)
- [Chrome OSで動くAndroidアプリの開発](https://gaprot.jp/2020/11/26/chrome-os/)
- [Chromium OS Configuration](https://chromium.googlesource.com/chromiumos/docs/+/master/os_config.md#crossystem)
- [ChromeOSの/etcを弄る](https://qiita.com/yas99en/items/9e21137b45ca5528f34b)