ESXi on Armで動くArch Linux ARM aarch64のイメージを作成する

# 何が難しいの?
[前の記事](https://qiita.com/air-gh/items/48740d160e0921d203b5)でESXi on ARMがRaspberry Pi 4のiSCSIで動作したので、vmを立てたくなる。
Ubuntuは、open-vm-toolsを手動ビルドする以外は、普通だった。
Arch Linux ARMは?

## Arch Linux ARMの対応プラットフォーム
対応プラットフォームは[こちら](https://archlinuxarm.org/platforms)。Raspberry Pi 4はあるが、ESXiは無い。
配布プラットフォームは[こちら](https://archlinuxarm.org/about/downloads)。Raspberry Pi 4はあるが、ESXiは無い。Multi-platformというのはある。

そして気づく。ISOイメージの配布が無い。tar.gzによる、rootファイルシステムのファイル配布である。

## ARM環境
よく考えると、当たり前に、ややこしい。
ARM自体に複数のISAがあるし、ボードのストレージの種類やサイズもまちまち。
BIOS設定や光学メディアからの起動は、無いほうが普通。
PCと同じ考えのESXiで、どうやってインストールするの?

# 動かし方
思いついたのは2種類。

- 配布ファイルからISOイメージを作成する
- 配布ファイルからvmdkイメージを作成する

ISOイメージ作成は[Archiso](https://wiki.archlinux.jp/index.php/Archiso)という便利な仕組みがあるが、オフィシャルには[x86_64のみ対応](https://git.archlinux.org/archiso.git/tree/docs/README.build#n67)。
これをaarch64に対応させるには、スクリプトを改造した上で、aarch64で動作しているArch Linuxで動作させるか、x86_64上にaarch64用のバイナリを置くか…。

## Arch Linux ARMのRaspberry Pi 4での動かし方
[こちら](https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-4)を読むと、

- SDカードに2つのパーティションを(GPTではなく)MBRで作成
- FAT側にbootを、ext4側にrootを入れる

というのが基本的な考えらしい。
SDだからMBRなのかな。[MBRのパーティション識別子](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%96%E3%83%BC%E3%83%88%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89)は0x0cなので、[EFIシステムパーティション](https://ja.wikipedia.org/wiki/EFI%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3)ではない普通のFAT32から起動するのか。

Raspberry Pi 4でArch Linux ARMを使ってみて分かったが、インストールするのではなく、このようにして作ったSDカードをそのまま使うイメージなのね。Raspberry Pi OSと同じ。そりゃそうだ、ストレージは通常、この起動SDしか無い。

ESXi on ArmはUEFIも対応しているので、同じ考えでMulti-platformのvmdkイメージを作れば、起動しそうな気がする。

# vmdkイメージの作り方
[Virtual Disk Development Kit (VDDK)](https://code.vmware.com/web/sdk/7.0/vddk)の使用も考えたが、今回は2つのパーティションの作成からなので、普通にブロックデバイスとして操作したい。
色々試してたどり着いた方法が、以下。

[前の記事](https://qiita.com/air-gh/items/48740d160e0921d203b5)と同じく、イメージ作成環境はUbuntu 20.04(x86_64, ext4)、ESXiはESXi on Arm Fling (Build 17230755)で確認。

## 空のddイメージの作成
```
fallocate -l 4GiB alarm-aarch64.img
```
容量は適当。[fallocate対応ファイルシステム](https://manpages.ubuntu.com/manpages/focal/en/man1/fallocate.1.html)でない場合は`dd if=/dev/zero`で作成。
時々出てくるalarmは、Arch Linux ARMの略と想像。

## ddイメージのloopbackデバイスへのsetup
```
losetup -f
```
で、空きループバックデバイスを取得し、/dev/loop14が取得できたので、

```
sudo losetup /dev/loop14 alarm-aarch64.img
```
で、/dev/loop14にsetup。

## パーティションの作成
```
sudo gdisk /dev/loop14
```
で、GPTでESP([推奨の512MiB](https://wiki.archlinux.jp/index.php/EFI_%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3), コード=EF00)とext4(残り全部, コード=デフォルトの8300)を作成。
`gdisk`の`i`コマンドで、ext4側のPartition unique GUIDを取得しておく。後で必要になる。

```
sudo partprobe /dev/loop14
```
で、GPTをロード。

## ファイルシステムの作成
ここからは、[Raspberry Pi 4の手順](https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-4)とだいたい同じ。mountまでを行う。

```
sudo mkfs.vfat /dev/loop14p1
mkdir boot
sudo mount /dev/loop14p1 boot

sudo mkfs.ext4 /dev/loop14p2
mkdir root
sudo mount /dev/loop14p2 root
```

## ファイルの展開と編集
```
sudo bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C root
sync
```
[Raspberry Pi 4の手順](https://archlinuxarm.org/platforms/armv8/broadcom/raspberry-pi-4)が`tar`ではなく`bsdtar`なのは、tar.gzに`LIBARCHIVE.xattr.security.capability`という属性が使われているからっぽい。詳細未調査。

```
sudo mv root/boot/* boot
```
で、bootの内容をESPに持ってくる。

さらに、`boot/startup.nsh`に、以下の内容を記述する。ここは、Raspberry Piには無い手順。

```boot/startup.nsh
\Image root=PARTUUID=da01e21e-7b80-4561-ac9a-9fd06c46691f rw initrd=/initramfs-linux.img
```
PARTUUIDの値は、gdiskのPartition unique GUIDで取得しておいた値。
ポイントは、Imageの前は`/`ではなく`\`、[PARTUUIDの値は小文字](https://wiki.archlinux.jp/index.php/%E6%B0%B8%E7%B6%9A%E7%9A%84%E3%81%AA%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AE%E5%91%BD%E5%90%8D)にする、など。
PARTUUIDの値は、gdiskの結果のコピペだと、大文字になってしまうので、注意。

Arch Linuxでは[EFISTUBがデフォルトで有効](https://wiki.archlinux.jp/index.php/EFISTUB)とあり、generic(=Multi-platform)にもEFI-stubbed Imageと[書かれている](https://archlinuxarm.org/platforms/armv8/generic)。
…というのを後から知った。最初に`Image`の中身を見たら、頭にMZとあったので、これは[PE](https://ja.wikipedia.org/wiki/Portable_Executable)なので[EFISTUB](https://wiki.archlinux.jp/index.php/EFISTUB)！ブートローダーを入れなくても起動できる！と思った次第。

## unmount
```
sudo umount root
sudo umount boot
sudo losetup -d /dev/loop14
```

## ddイメージのvmdkへの変換
```
qemu-img convert -f raw alarm-aarch64.img -O vmdk alarm-aarch64-qemu.vmdk
```
vmdkのファイル名を`-qemu`としたのは、次にもう1工程あるため。

## ESXi上でのvmdkイメージの変換
vmdkイメージを転送した上で、ESXiでsshを有効にして、

```
vmkfstools -i alarm-aarch64-qemu.vmdk -d thin alarm-aarch64.vmdk
```

で、vmdkをCloneする。こうしないと、ディスクイメージをインポートして起動後、`「sata0:2」用のディスク タイプ 2 がサポートされていないか無効です。`というエラーが出てしまった。
なお、ググるとたまに出てくる`-a`によるadaptertype指定は、ESXi 6.5から[廃止になった](https://kb.vmware.com/s/article/1002511?lang=ja)そうだ。

# 起動
ここまででようやくvmdkイメージができたので、イメージをインポートして起動と行きたいところだが、もう1つ。
`startup.nsh`を実行するために、UEFI設定で、UEFI shellから起動する必要がある。

`仮想マシン->設定->仮想マシンオプション->強制的にBIOSセットアップ`をチェックし、
`Boot Manager->EFI Internal Shell`を選択。数秒待つと`startup.nsh`が呼ばれ、めでたくArch Linuxの起動となる…はず。

# 宿題
長い道のりだったが、道半ば。

- `pacman -Syu`すると、何故かE1000eが認識しなくなる
- `linux-aarch64`は[VMXNET3が無効](https://archlinuxarm.org/packages/aarch64/linux-aarch64/files/config)
- Ubuntuと同様、`open-vm-tools`はパッケージ化されていない模様
- UEFI Shellを選択しなくてもいいように、ブートローダーをインストールしたい

こんなことを手作業でやらなくても自動でやってくれる何かがあるに違いない！(フラグ)