Ubuntu Linux 起動ディスクを BIOS ブートから EFI ブートへ変換

## はじめに

この記事では、[記事: Ubuntu VM の移行 (VMware から Hyper-V へ)](https://shigeyf.dev/posts/convert-ubuntu-disk-from-bios-to-efi/../migrate-ubuntu-vm-from-vmware-to-hyper-v/)
で説明した以下の移行手順の ステップ 4 について説明します。

1. VMDK 形式の仮想ディスクを VHD/VHDX 形式への変換
2. 新しい仮想マシンを作成 (変換した仮想ディスクをアタッチする)
3. open-vm-tools のアンインストール
4. (オプション) **第2世代 Hyper-V 仮想マシン用の仮想ディスクへ変換**
5. (オプション) Secure Boot の有効化
6. Hyper-V 統合サービスのインストール

## Ubuntu Linux 起動ディスクを BIOS ブートから EFI ブートへ変換

第 2 世代 Hyper-V 仮想マシンで Ubuntu Linux を起動するには、
Ubuntu Linux の起動ディスクを BIOS ブートから EFI ブートへ変更する必要があります。

起動ディスクを EFI ブートに変更するには、Ubuntu インストーラー メディア (ライブサーバー) を使って以下の手順で行います。

1. [新しい第2世代 Hyper-V 仮想マシンを作成する](#ステップ-1-新しい第-2-世代-hyper-v-仮想マシンの作成)
2. [パーティションのサイズの縮小](#ステップ-2-パーティションのサイズの縮小)
3. [EFI パーティションの作成](#ステップ-3-efi-パーティションの作成) (EFI パーティションはディスクの最後尾に準備)
4. [Grub EFI のインストール](#ステップ-4-grub-efi-のインストール)
5. [/etc/fstab の編集](#ステップ-5-etcfstab-の編集)

インストーラーメディアは[こちらのサイト](https://ubuntu.com/download/server)からダウンロードします

### ステップ 1: 新しい第 2 世代 Hyper-V 仮想マシンの作成

この移行作業は EFI ブート対応の仮想マシンで実行する必要があるため、第 2 世代 Hyper-V の新しい仮想マシンを作成する。
仮想マシンを作成したら、仮想マシンの設定から、**[セキュリティ]** -> **[セキュアブートを有効にする]**　のチェックボックスを外します。

仮想マシンの設定の **[SCSI コントローラー]** から **[DVD Drive]** を追加し、
ダウンロード済みの Ubuntu Server インストーラーメディアをイメージファイルに設定します。

また、仮想マシンの設定の **[ファームウェア]** では、**[DVD Drive]** からの起動を優先するよう、
一番上のエントリとなるように設定します。

インストーラーが起動したら、右上に表示された **[ Help ]** を選択し、**Enter shell** を選択して、
シェルコンソールを起動します。

> ライブサーバーは外部から SSH でリモートアクセスすることも可能です。
>
> **[ Help ]** -> **Help on SSH access** でリモートアクセスのためのユーザー名とパスワードを確認することができます。

### ステップ 2: パーティションのサイズの縮小

EFI パーティションを確保するために、パーティションのサイズを縮小します。

EFI パーティションは 2 GB の容量を確保することを目標とします。

#### ステップ 2-1: パーティションの確認

まず、最初に、現在のパーティションと使用状況を以下のコマンドで確認します。

```bash
lsblk /dev/sda && pvs && vgs && lvs
```

コマンドの出力結果は以下の通りです。

```text
NAME                      MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda                         8:0    0  32G  0 disk
|-sda1                      8:1    0   1M  0 part
|-sda2                      8:2    0   2G  0 part
`-sda3                      8:3    0  30G  0 part
  `-ubuntu--vg-ubuntu--lv 253:0    0  15G  0 lvm

  PV         VG        Fmt  Attr PSize   PFree
  /dev/sda3  ubuntu-vg lvm2 a--  <30.00g 15.00g

  VG        #PV #LV #SN Attr   VSize   VFree
  ubuntu-vg   1   1   0 wz--n- <30.00g 15.00g

  LV        VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  ubuntu-lv ubuntu-vg -wi-a----- <15.00g
```

| パーティション名 | 説明 | サイズ |
| --- | --- | --- |
| sda1 | BIOS ブート用のパーティション | 1 MB |
| sda2 | /boot (ブートローダー用) パーティション | 2 GB |
| sda3 | システム (root) パーティションを含む論理ボリュームを格納したパーティション | 30 GB |
| ubuntu--vg-ubuntu--lv | 論理ボリューム | 15 GB 使用中 |

物理ボリュームのボリュームグループ (`ubuntu-vg`) は、パーティションサイズ全体に割り当てられていて、
ボリュームグループ内の論理ボリューム (`ubuntu-lv`) は現在 15 GB 使用中です。

この例では、ボリュームグループに空きがあるため、論理ボリュームのサイズを変更する必要はありません。

#### ステップ 2-2: 論理ボリュームのサイズを縮小する

ここで取り上げた例では、論理ボリュームのサイズの変更をする必要はありませんが、
論理ボリュームのサイズを変更する方法を説明します。

##### 1) 空き容量の確認

まず、論理ボリューム内の空き容量を確認するために、以下のコマンドを実行します。

```bash
mount /dev/mapper/ubuntu--vg-ubuntu--lv /mnt
df /mnt
umount /mnt
```

15 GB 中の 42% 使用中となっており、論理ボリュームのサイズを縮小することができます。

```text
Filesystem                        1K-blocks    Used Available Use% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv  15371208 6115404   8453196  42% /mnt
```

##### 2) ファイルシステムのエラーチェック

論理ボリュームのサイズを縮小する前に、ファイルシステムのエラーチェックを行います。

```bash
e2fsck -f -v /dev/mapper/ubuntu--vg-ubuntu--lv
```

##### 3) ファイルシステムのサイズの縮小

次に、ファイルシステムのサイズを縮小します。

```bash
resize2fs -p /dev/mapper/ubuntu--vg-ubuntu--lv 13G
```

##### 4) 論理ボリュームのサイズの縮小

最後に、論理ボリュームのサイズを縮小するために、以下のコマンドを実行します。
この例では、2 GB のサイズを縮小 (`13GB`) します。

```bash
lvresize -L 13G /dev/ubuntu-vg/ubuntu-lv && lvs
```

コマンドの出力結果は以下の通りとなり、15 GB から 2 GB 縮小し、13 GB となりました。

```
  WARNING: Reducing active logical volume to <13.00 GiB.
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce ubuntu-vg/ubuntu-lv? [y/n]: y
  Size of logical volume ubuntu-vg/ubuntu-lv changed from <15.00 GiB (3839 extents) to <13.00 GiB (3327 extents).
  Logical volume ubuntu-vg/ubuntu-lv successfully resized.

  LV        VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  ubuntu-lv ubuntu-vg -wi-a----- <13.00g
```

再度、ファイルシステムのチェックを行い、問題がないか確認します。

```bash
e2fsck -f -v /dev/mapper/ubuntu--vg-ubuntu--lv
```

#### ステップ 2-3: 物理ボリュームのサイズを縮小する

以下のコマンドを実行して、物理ボリュームの使用状況を再度確認します。

```bash
pvs
```

コマンドの出力結果は以下の通りで、17 GB の空き状況となっています。

```
  PV         VG        Fmt  Attr PSize   PFree
  /dev/sda3  ubuntu-vg lvm2 a--  <30.00g 17.00g
```

次に、物理ボリュームのサイズを縮小するために、以下のコマンドを実行します。
この例では、元の 30 GB のサイズを 28 GB に縮小します。

```bash
pvresize --setphysicalvolumesize 28g /dev/sda3
```

```text
/dev/sda3: Requested size 28.00 GiB is less than real size <30.00 GiB. Proceed?  [y/n]: y
  WARNING: /dev/sda3: Pretending size is 58720256 not 62908416 sectors.
  Physical volume "/dev/sda3" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized
```

`pvs` コマンドの出力結果は以下の通りとなり、28 GB のサイズへ変更されました。

```
  PV         VG        Fmt  Attr PSize   PFree
  /dev/sda3  ubuntu-vg lvm2 a--  <28.00g 15.00g
```

#### ステップ 2-4: パーティション テーブルの変更

LVM の物理ボリューム・論理ボリュームを変更操作では、パーティションの情報は変更されないため、
以下のコマンドの実行結果の通り、パーティションは依然として 30 GB のサイズのままとなっています。

```bash
lsblk /dev/sda3
```

コマンドの出力結果:

```text
NAME                    MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda3                      8:3    0  30G  0 part
`-ubuntu--vg-ubuntu--lv 253:0    0  13G  0 lvm
```

`fdisk /dev/sda` とコマンドを実行して、パーティションテーブルを書き換えます。
`fdisk` はインタラクティブ操作のツールとなっていて、コマンドは以下の通りです。

* 'p' コマンド: パーティション テーブルの表示
* 'd' コマンド: パーティション テーブルの削除
* 'n' コマンド: パーティション テーブルの作成

コマンド実行の様子は以下の通りで、既存のパーティション テーブルの削除、新しいパーティション テーブルの操作により、
パーティションのテーブルの書き換えを行います。ただし、パーティションに含まれるシグネチャ情報を削除しないように注意してください。

```text
Welcome to fdisk (util-linux 2.37.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): p   <== 'p' を入力する

Disk /dev/sda: 32 GiB, 34359738368 bytes, 67108864 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 9DB29DC2-4F7D-4E2A-B917-31BE798E6613

Device       Start      End  Sectors Size Type
/dev/sda1     2048     4095     2048   1M BIOS boot
/dev/sda2     4096  4198399  4194304   2G Linux filesystem
/dev/sda3  4198400 67106815 62908416  30G Linux filesystem

Command (m for help): d   <== 'd' を入力する
Partition number (1-3, default 3): 3   <== '3' を入力する

Partition 3 has been deleted.

Command (m for help): n   <== 'n' を入力する
Partition number (3-128, default 3): 3   <== '3' を入力する
First sector (4198400-67108830, default 4198400):   <== ENTER を入力する
Last sector, +/-sectors or +/-size{K,M,G,T,P} (4198400-67108830, default 67108830): +28G   <== '+28G' を入力する

Created a new partition 3 of type 'Linux filesystem' and of size 28 GiB.
Partition #3 contains a LVM2_member signature.

Do you want to remove the signature? [Y]es/[N]o: N   <== 'N' を入力する

Command (m for help): p   <== 'p' を入力する

Disk /dev/sda: 32 GiB, 34359738368 bytes, 67108864 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 9DB29DC2-4F7D-4E2A-B917-31BE798E6613

Device       Start      End  Sectors Size Type
/dev/sda1     2048     4095     2048   1M BIOS boot
/dev/sda2     4096  4198399  4194304   2G Linux filesystem
/dev/sda3  4198400 62918655 58720256  28G Linux filesystem

Command (m for help): w   <== パーティションを確認し、問題なければ 'w' を入力して、パーティションテーブル情報をディスクに書き込む
The partition table has been altered.
Syncing disks.
```

物理ボリュームに問題がないか、以下のコマンドを実行します。

```bash
pvdisplay
```

コマンドの出力結果は以下の通りです。

```
  --- Physical volume ---
  PV Name               /dev/sda3
  VG Name               ubuntu-vg
  PV Size               <28.00 GiB / not usable 3.00 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              7167
  Free PE               3840
  Allocated PE          3327
  PV UUID               50Kkwj-1v59-d5IX-GNUS-Goph-v6fo-5p7CKU
```

### ステップ 3: EFI パーティションの作成

#### 1) EFI パーティション テーブルの作成

`fdisk` コマンドを使って、EFI パーティションを作成します。

```text
Welcome to fdisk (util-linux 2.37.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.


Command (m for help): p   <== 'p' を入力する

Disk /dev/sda: 32 GiB, 34359738368 bytes, 67108864 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 9DB29DC2-4F7D-4E2A-B917-31BE798E6613

Device       Start      End  Sectors Size Type
/dev/sda1     2048     4095     2048   1M BIOS boot
/dev/sda2     4096  4198399  4194304   2G Linux filesystem
/dev/sda3  4198400 62918655 58720256  28G Linux filesystem

Command (m for help): n   <== 'n' を入力する
Partition number (4-128, default 4): 4   <== '4' を入力する
First sector (62918656-67108830, default 62918656):   <== ENTER を入力する
Last sector, +/-sectors or +/-size{K,M,G,T,P} (62918656-67108830, default 67108830):   <== ENTER を入力する

Created a new partition 4 of type 'Linux filesystem' and of size 2 GiB.

Command (m for help): t   <== 't' を入力する
Partition number (1-4, default 4): 4   <== '4' を入力する
Partition type or alias (type L to list all): 1   <== '1' を入力する

Changed type of partition 'Linux filesystem' to 'EFI System'.

Command (m for help): w   <== 'w' を入力する
The partition table has been altered.
Syncing disks.
```

#### 2) EFI パーティションのフォーマット

まず、以下のコマンドでパーティション情報を確認します。

EFI パーティションは `/dev/sda4` となります。

```bash
lsblk /dev/sda
```

コマンドの実行結果:

```text
NAME                      MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda                         8:0    0  32G  0 disk
|-sda1                      8:1    0   1M  0 part
|-sda2                      8:2    0   2G  0 part
|-sda3                      8:3    0  28G  0 part
| `-ubuntu--vg-ubuntu--lv 253:0    0  13G  0 lvm
`-sda4                      8:4    0   2G  0 part
```

以下のコマンドを実行して、`/dev/sda4` パーティションを FAT32 でフォーマットします。

```bash
mkfs.vfat -v -c -F 32 /dev/sda4
```

コマンドの実行結果:

```text
mkfs.fat 4.2 (2021-01-31)
/dev/sda4 has 255 heads and 63 sectors per track,
hidden sectors 0x3c01000;
logical sector size is 512,
using 0xf8 media descriptor, with 4190130 sectors;
drive number 0x80;
filesystem has 2 32-bit FATs and 8 sectors per cluster.
FAT size is 4088 sectors, and provides 522740 clusters.
There are 32 reserved sectors.
Volume ID is ad004b99, no volume label.
Searching for bad blocks
```

### ステップ 4: Grub EFI のインストール

EFI パーティションの作成が完了したら、EFI ブート用の Grub ブートローダーをインストールします。

#### 1) 起動ディスクのマウント

以下のコマンドを実行し、起動ディスクをマウントします。

```bash
mount /dev/ubuntu-vg/ubuntu-lv /mnt
mount /dev/sda2 /mnt/boot/
mkdir /mnt/boot/efi
mount /dev/sda4 /mnt/boot/efi
```

#### 2) boot パーティションのバックアップ

以下のコマンドを実行し、起動ディスクの /boot パーティションのバックアップをとります。

```bash
cp -rp /mnt/boot /mnt/boot2
```

#### 3) Grub EFI パッケージの取得

以下のコマンドを実行し、Grub EFI パッケージをネットワーク経由でダウンロードし、ライブサーバー環境にインストールします。

```bash
apt update
apt install grub-efi-amd64 -y
```

#### 4) Grub EFI のインストール

以下のコマンドを実行し、起動ディスクに Grub EFI をインストールします。

```bash
cp -rp /mnt/boot/grub /mnt/boot/grub.old
mkdir /mnt/boot/efi/EFI

for i in /usr /dev /dev/pts /proc /sys /sys/firmware/efi/efivars /run; do mount --bind $i /mnt$i; done

chroot /mnt

grub-install --target=x86_64-efi /dev/sda
grub-install --recheck /dev/sda

update-grub2
```

### ステップ 5: /etc/fstab の編集

Grub EFI ブートローダーのインストールが完了したら、
最後に /etc/fstab を編集して、EFI パーティションをマウントするよう設定します。

以下のコマンドを実行し、パーティションの UUID を確認します。

```bash
blkid /dev/sda4
```

コマンドの実行結果:

```text
/dev/sda4: UUID="XXXX-XXXX" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="5c027d5d-e842-b54c-a013-ee2c6a325b19"
```

上記の "XXXX-XXXX" がパーティションの UUID となります。
パーティションごとに固有の UUID となりますので、それぞれの環境の UUID に置き換えてください。

以下のコマンドを実行して、`/mnt/etc/fstab` にマウントポイントのエントリを追加します。

```bash
echo "/dev/disk/by-uuid/XXXX-XXXX /boot/efi vfat defaults 0 1" >> /mnt/etc/fstab
```

## 最後に

以上の作業により、EFI ブートが可能なディスクに変更されました。
ライブサーバーを `reboot` コマンドで再起動すると、第 2 世代 Hyper-V 仮想マシンで Ubuntu Linux が起動できるようになります。

セキュアブートを有効にした構成にはなっていないため、仮想マシンの設定ではセキュアブートを無効にしたままにします。

Ubuntu Linux 16.06 以降のバージョンでは、マイクロソフトの提供する Ubuntu Linux 用のセキュアブート環境が用意されています。
詳細な手順については、[こちらの記事](https://shigeyf.dev/posts/convert-ubuntu-disk-from-bios-to-efi/../enable-secure-boot-in-ubuntu-vm/) を参照ください。