yoctoビルドしたimageをvirt-managerにimportする

# 1. はじめに

## 1.1. 動機

- 最近、yoctoビルドについてゼロから学んでいるのですが、yoctoのエミュレータにはqemuが使用されています。
- qemu自体は、私も過去LinuxKVMを通して使用してきたこともあるため、「もしかしてLinuxKVMを用いて仮想マシンとして動作させられるのでは？」と考えておりました。
  - ただし、検索してもvirt-manager等でyoctoビルドしたイメージを動かす事例に行き着くことができませんでした。
- 今回、参考資料[1][2]をもとに、core-image-minimalをvirt-managerで仮想マシン化することができたため、その方法についてまとめます。
  - なお、本ページではLinuxKVMやvirt-managerのインストール方法については扱いません。

## 1.2. 開発環境

- OS: Ubuntu22.04
- CPU: Core(TM) i7-12700
- RAM: 32GB
- 利用ツール
  - VS Code
  - Docker (devcontainer利用)

## 1.3. リポジトリ

- https://github.com/tomoten-umino/my-yocto-devcontainer
  - yocto環境構築用のdevcontainerとして利用しています。
  - ただし、参考資料[3]を参照してcore-image-minimalをビルドできる環境を用意すれば、そちらを使用いただいてよいです。
- https://github.com/mendersoftware/meta-mender
  - mender社が公開しているmeta-menderレイヤーとなります。本記事では、こちらを利用します。


## 1.4. 参考資料

| No. | URL | 説明 |
| :-- | :-- | :-- |
| [1] | [Running QEMU Images with virtio, virsh and virt-manager, Tim Orling](https://www.youtube.com/watch?v=VW83osfqHpY) | yoctoイメージをvirt-managerで動かしたことを紹介したyoutube動画 |
| [2] | [MENDER docs Building for demo](https://docs.mender.io/operating-system-updates-yocto-project/build-for-demo) | 適用するmeta-menderについてのmenter社のドキュメント |
| [3] | [Yocto Project Quick Build](https://docs.yoctoproject.org/4.0.21/brief-yoctoprojectqs/index.html) | Yoctoビルドのガイド |

# 2. core-image-minimalのビルド

## 2.1. yocto環境の用意

- HostOS側にて、my-yocto-devcontainerをgit cloneし、ルートフォルダにてVS Codeを開きます。

```shell
git clone https://github.com/tomoten-umino/my-yocto-devcontainer.git
cd my-yocto-devcontainer
code .
```

- "Reopen in Container" を選択し、devcontainerを起動させます。
  - VS Codeが開き、コンテナにログインした状態となります。
  - コンテナ内のworkdirにmy-yocto-devcontainerのルートフォルダがマウントされた状態となります。
- pokyを取得します。本資料では、kirkstoneを利用します。

```shell
git clone -b kirkstone git://git.yoctoproject.org/poky
```

- oe-init-build-envを読み込んで、環境変数セットとbuildディレクトリを作成します。

```shell
source ./poky/oe-init-build-env build
```

- この段階で、workdir以下は以下のような構成となります。

```shell
workdir
├── build
├── poky
├── README.md
└── UNLICENSE
```

## 2.2. core-image-minimalのビルド

- buildディレクトリにて、core-image-minimalをビルドします。
  - bitbakeでのビルドには時間がかかります。

```shell
# buildディレクトリにて
bitbake core-image-minimal
```

- ビルドが完了すると、tmp/deploy/images/qemux86-64以下にイメージが作成されます。
  - ただし、この状態ではuefi用のimgファイルがありません。


```shell
# core-image-minimalのイメージが作成される 
./tmp/deploy/images/qemux86-64
├── bzImage -> bzImage--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923125041.bin
├── bzImage--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923125041.bin
├── bzImage-qemux86-64.bin -> bzImage--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923125041.bin
├── core-image-minimal-qemux86-64-20240923125041.qemuboot.conf
├── core-image-minimal-qemux86-64-20240923125041.rootfs.ext4
├── core-image-minimal-qemux86-64-20240923125041.rootfs.manifest
├── core-image-minimal-qemux86-64-20240923125041.rootfs.tar.bz2
├── core-image-minimal-qemux86-64-20240923125041.testdata.json
├── core-image-minimal-qemux86-64.ext4 -> core-image-minimal-qemux86-64-20240923125041.rootfs.ext4
├── core-image-minimal-qemux86-64.manifest -> core-image-minimal-qemux86-64-20240923125041.rootfs.manifest
├── core-image-minimal-qemux86-64.qemuboot.conf -> core-image-minimal-qemux86-64-20240923125041.qemuboot.conf
├── core-image-minimal-qemux86-64.tar.bz2 -> core-image-minimal-qemux86-64-20240923125041.rootfs.tar.bz2
├── core-image-minimal-qemux86-64.testdata.json -> core-image-minimal-qemux86-64-20240923125041.testdata.json
├── modules--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923125041.tgz
└── modules-qemux86-64.tgz -> modules--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923125041.tgz
```

# 3. meta-mender導入とcore-image-minimalの再ビルド

## 3.1. meta-menderについて

- 参考資料[2]の[Introduction](https://docs.mender.io/overview/introduction)によると、meta-mender自体は、deviceのsoftware updateのシステム機能を提供するもののようです。

## 3.2. meta-memderレイヤーの追加

- build, pokyと同じディレクトリにて、meta-menderをgit cloneします。

```shell
git clone -b kirkstone https://github.com/mendersoftware/meta-mender
```

- buildディレクトリにて、meta-mender-coreをaddします。

```shell
bitbake-layers add-layer ../meta-mender/meta-mender-core
```

- add-layerが成功すると、build/conf/bblayers.confにmeta-mender-coreが追加されます。

```shell
# bblayers.conf
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  /workdir/poky/meta \
  /workdir/poky/meta-poky \
  /workdir/poky/meta-yocto-bsp \
  /workdir/meta-mender/meta-mender-core \
  "
```

- この段階で、workdir以下は以下のような構成となります。

```shell
workdir
├── build
├── meta-mender
├── poky
├── README.md
└── UNLICENSE
```

## 3.3. local.confの修正

- build/conf/local.conf の末尾に以下を追加します。
  - 参考資料[2]のうち、特に[filesystem tipes](https://docs.mender.io/operating-system-updates-yocto-project/board-integration/partition-configuration#filesystem-types)と[Configuring strage](https://docs.mender.io/operating-system-updates-yocto-project/board-integration/partition-configuration#configuring-storage)の設定が重要となります。
  - とくに、```MENDER_STORAGE_DEVICE``` のデフォルト値は ```/dev/mmcblk0"``` となっています。LinuxKVMで仮想マシンを稼働させる場合、vdiskは ```/dev/vda```　をマウントするため、修正が必須となります。

```shell
# local.conf に以下を追加する
# User settings
MENDER_ARTIFACT_NAME = "release-1"
INHERIT += "mender-full"
MACHINE = "qemux86-64"
MENDER_STORAGE_DEVICE = "/dev/vda"
```

## 3.4. core-image-minimalの再ビルド

- buildディレクトリにて、再度core-image-minimalをビルドします。
  - bitbakeでのビルドには時間がかかります。
- ビルドが完了すると、tmp/deploy/images/qemux86-64以下にイメージが作成されます。
  - uefi用のimgファイルとして、.uefiimgが生成されています。

```shell
./tmp/deploy/images/qemux86-64
├── bzImage -> bzImage--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923165336.bin
├── bzImage--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923165336.bin
├── bzImage-qemux86-64.bin -> bzImage--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923165336.bin
├── core-image-minimal.env
├── core-image-minimal-qemux86-64-20240923165336.bootimg
├── core-image-minimal-qemux86-64-20240923165336.bootstrap-artifact
├── core-image-minimal-qemux86-64-20240923165336.dataimg
├── core-image-minimal-qemux86-64-20240923165336.ext4
├── core-image-minimal-qemux86-64-20240923165336.manifest
├── core-image-minimal-qemux86-64-20240923165336.mender
├── core-image-minimal-qemux86-64-20240923165336.qemuboot.conf
├── core-image-minimal-qemux86-64-20240923165336.tar.bz2
├── core-image-minimal-qemux86-64-20240923165336.testdata.json
├── core-image-minimal-qemux86-64-20240923165336.uefiimg
├── core-image-minimal-qemux86-64-20240923165336.uefiimg.bmap
├── core-image-minimal-qemux86-64-20240923165336.uefiimg.bz2
├── core-image-minimal-qemux86-64.bootimg -> core-image-minimal-qemux86-64-20240923165336.bootimg
├── core-image-minimal-qemux86-64.bootstrap-artifact -> core-image-minimal-qemux86-64-20240923165336.bootstrap-artifact
├── core-image-minimal-qemux86-64.dataimg -> core-image-minimal-qemux86-64-20240923165336.dataimg
├── core-image-minimal-qemux86-64.ext4 -> core-image-minimal-qemux86-64-20240923165336.ext4
├── core-image-minimal-qemux86-64.manifest -> core-image-minimal-qemux86-64-20240923165336.manifest
├── core-image-minimal-qemux86-64.mender -> core-image-minimal-qemux86-64-20240923165336.mender
├── core-image-minimal-qemux86-64.qemuboot.conf -> core-image-minimal-qemux86-64-20240923165336.qemuboot.conf
├── core-image-minimal-qemux86-64.tar.bz2 -> core-image-minimal-qemux86-64-20240923165336.tar.bz2
├── core-image-minimal-qemux86-64.testdata.json -> core-image-minimal-qemux86-64-20240923165336.testdata.json
├── core-image-minimal-qemux86-64.uefiimg -> core-image-minimal-qemux86-64-20240923165336.uefiimg
├── core-image-minimal-qemux86-64.uefiimg.bmap -> core-image-minimal-qemux86-64-20240923165336.uefiimg.bmap
├── core-image-minimal-qemux86-64.uefiimg.bz2 -> core-image-minimal-qemux86-64-20240923165336.uefiimg.bz2
├── grub-efi-bootx64.efi
├── linuxx64.efi.stub
├── modules--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923165336.tgz
├── modules-qemux86-64.tgz -> modules--5.15.166+git0+567f0adb9d_a78a104311-r0-qemux86-64-20240923165336.tgz
└── systemd-bootx64.efi
```

# 4. virt-managerへのインポート

新しい仮想マシンの作成のダイアログにしたがってインポートしますが、以下の点に気をつけて進めます。

- オペレーティングシステムのインストール方法は、「既存のディスクイメージをインポート」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/498cf356-0364-f37a-f0d5-32bf4774e716.png)

- ストレージパスを指定するときは、上記でビルドしたイメージファイルのうち、```core-image-minimal-qemux86-64.uefiimg``` を指定します。
- オペレーティングシステムの選択としては、```Generic Linux2022```を選択します。
  - 適合するものが無いため、Generic Linux2022にしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/bd73d010-d3fa-cce3-a3a9-2bf543322a85.png)

- メモリとCPUの設定は、お好みで設定します。

- インストール準備を始める前に、「インストールの前にカスタマイズする」にチェックを入れて「完了」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/14240e0b-b836-3b0c-3f4d-49623d02a49f.png)

- カスタマイズ画面にて、ファームウェアを```OVMF_CODE_4M.fd```に変更し、適用します。その後、「インストールの開始」を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/c5dd3eda-7534-de06-1bcf-62f587ae9f34.png)

- 仮想マシンが起動し、login画面となれば、起動成功です。
  - core-image-minimalのデフォルトのため、rootでログインできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/ea5c475c-a58f-0b6a-c768-89954cc50ba2.png)

# 5. おわりに

- 本ページ作成時点、3.4. core-image-minimalの再ビルドでyoctoビルドエラーが7つ残っています。
  - こちらは、順次確認します。
- LinuxKVMの仮想マシンとしてインポートできることを確認できました。そのため、virt-managerの編集画面からCPUやメモリ、デバイスの追加等などのカスタマイズ性が向上すると思います。
- 今回は、meta-menderレイヤーを利用しましたが、uefiimgの作成処理を勉強させていただき、自分でLinuxKVMにインポートできる形式のimgファイルやqcow2ファイルを生成できるようにしたいと思っております。

# 6. （追加）core-image-satoのビルド

## 6.1. local.confへの追加、ビルド

- 3.3. local.confの修正に加えて、以下のMENDER_STORAGE_TOTAL_SIZE_MBを指定します。
  - これは、core-image-satoのビルド結果のimgサイズがデフォルトのサイズを超過してしまうためです。

```shell
# local.conf に以下を追加する
# User settings
MENDER_ARTIFACT_NAME = "release-1"
INHERIT += "mender-full"
MACHINE = "qemux86-64"
MENDER_STORAGE_DEVICE = "/dev/vda"
MENDER_STORAGE_TOTAL_SIZE_MB = "2048"
```

- buildディレクトリにて、core-image-satoをビルドします。
  - やはりビルドには時間がかかります。
  - ビルド完了後、core-image-sato-qemux86-64.uefiimg が生成されます。

## 6.2. virt-managerへのインポート

- 4. virt-managerへのインポート と同様の進め方でインポートします。
- 仮想マシンを起動するとGUIが起動し、操作できることが確かめられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/fc9db49b-ac4c-d8f1-ee9d-5137353226dd.png)

- 試しにTerminalでwgetをしてみたところ、導通していることが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624259/bd7764a5-ccda-4b36-9b17-e6ea477260f9.png)