デュアルブート用UEFIソフトをつくる（第1回）

# 前回記事
https://qiita.com/meet4580/items/b15a9356e5820976c358

# おしながき
* 環境構築
* rEFIndを起動してみる

# 環境構築
## 使用するソフトウェア
今回の連載で使うソフトは、以下の3つです。
* QEMU（仮想マシン）
* OVMF（UEFIモードでQEMUを起動するイメージファイル）
* LLVM/clang（クロスコンパイラ）

勉強のため、EDK2やgnu-efiなどの開発キットは使わずに、仕様書そのものを見て開発していってみようと思います。

## インストール
3つのいずれも、Arch公式レポジトリからダウンロード・インストールできます。
```
# pacman -S qemu-full edk2-ovmf clang
```

## イメージファイルの用意
ルートディレクトリにある`OVMF`を、ホームディレクトリ内にコピーしてきます。実機ではNVRAMに相当するものが含まれます。
```
$ mkdir ~/qemu_vm/
$ cd ~/qemu_vm/
$ cp /usr/share/edk2/x64/OVMF.4m.fd ./
```
EFIシステムパーティションに相当するものがほしいので、まずは空のイメージファイルを作成します。今回は、適当に1GBのものをつくりました。
 ```
# dd if=/dev/zero of=./ESP.img bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.218497 s, 4.9 GB/s
 ```
イメージファイルを、EFIシステムパーティションと同じFAT32にフォーマットしておきます。
 ```
# mkfs.fat -F 32 ./ESP.img 
mkfs.fat 4.2 (2021-01-31)
 ```
FAT32にフォーマットされた、空のファイルシステムのイメージファイルができました。  

QEMUが2つのファイルを操作できるように、権限を変更しておきます。他グループのユーザーからの書き込み権限がないと、ファイル操作ができません。
```
# chmod 666 ./OVMF.4m.fd ./ESP.img
```

# QEMUの起動オプション
 ```
$ qemu-system-x86_64 \
-drive if=pflash,format=raw,file=./OVMF.4m.fd \
-drive if=virtio,format=raw,file=./ESP.img
 ```
いきなりいろんなオプションが出てきましたが、それぞれの意味は以下のとおりです。
### -driveオプションについて
>-drive option[,option[,option[,...]]]
>Define a new drive. This includes creating a block driver node (the backend) as well as a guest device, and is mostly a shortcut for defining the corresponding -blockdev and -device options.
>...
>file=file
>This  option  defines  which  disk  image (see the Disk Images chapter in the System Emulation Users Guide) to use with this drive.  If the filename contains comma, you must double it (for instance, "file=my,,file" to use file "my,file").
>...
>if=interface
>This option defines on which type on interface the drive is connected. Available types are: ide, scsi, sd, mtd, floppy, pflash, virtio, none.
>...
>format=format
>Specify which disk format will be used rather than detecting the format. Can be used to specify format=raw to avoid interpreting an untrusted format header.
>（man qemu(1) l.883より）

このオプションを使って、ドライブを指定します。
#### file
今回は、fd（Floppy Disk）形式と、img形式のファイルを使います。
#### if
どの媒体でディスクイメージを接続するか設定します。[QEMUのwiki](https://wiki.qemu.org/Features/PC_System_Flash)によると、pflashは、PCのシステムフラッシュメモリのエミュレーションだそうです。vertioは、仮想化環境で効率的にI/O操作を行うためのフレームワークです。
#### format
ディスクのファイルシステムのフォーマットを指定します。自動検出することもできるようですが、`format=raw`と指定することで、動作が保証されていないフォーマットとして解釈することを防いでくれるようです。

## 起動
 さて、とりあえずQEMUを起動してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735823/fb8a80cc-0e3f-baa7-3ee1-b2a722dddedf.png)
2025年1月13日時点での最新版はUEFI 2.11なので、UEFIは最新ではないようです。

https://uefi.org/sites/default/files/resources/UEFI%20Spec%202_7_A%20Sept%206.pdf

# 仮想環境にrEFIndをインストールしてみる
ベアメタルプログラミングを始める前に、練習として、仮想環境にrEFIndブートローダをインストールしてみます。
公式レポジトリからrEFIndをダウンロード、インストールします。
```
# pacman -S refind
```
ここからは、仮想環境のドライブのイメージファイルをいじっていきます。
ユーザーのuidとgidを調べます。
```
$ id xxxx(username)
uid=yyyy(xxxx) gid=zzzz(xxxx) groups=wwww(xxxx)
```
このユーザーが書き込み権限を持つように、イメージファイルをマウントします。ループバックデバイスを作るため、su権限が必要です。
```
$ mkdir ./mnt/
# mount -o uid=yyyy,gid=zzzz ./ESP.img ./mnt/
```
仮想環境のディスクの中に入り、階層構造をつくってrEFIndをインストールします。
```
$ cd ./mnt/
$ mkdir ./EFI/
$ mkdir ./EFI/BOOT/
$ cp /usr/share/refind/refind_x64.efi ./EFI/BOOT/bootx64.efi
$ cp -r /usr/share/refind/icons/ ./EFI/BOOT/
```
マウントを解除しておきます。
```
$ cd ..
# umount ./mnt/
```

## rEFIndの起動確認
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3735823/a6751302-ab90-d96d-c6b5-127cb5770771.png)
 上記画像の通り、rEFIndが起動しました。

 # 参考
 * https://uefi.org/sites/default/files/resources/UEFI%20Spec%202_7_A%20Sept%206.pdf
 * http://yuma.ohgami.jp/UEFI-Bare-Metal-Programming/index.html
 * https://eng-entrance.com/linux-mount
 * https://wiki.archlinux.jp/index.php/QEMU
 * https://kernhack.hatenablog.com/entry/2013/01/26/220758
 * https://qiita.com/jinnai73/items/b3209e95dec31d57c635