USBメモリや DVD などのリムーバブルメディアから起動可能な Ubuntu (以下 「Live Ubuntu」 と呼ぶ) は、 PC がトラブったときのレスキュー (障害復旧) の道具として重宝する。 最近の USBメモリは容量が大きく、 3GB 程度の Live Ubuntu を入れておいても大して邪魔にならない。 ふだん持ち歩く USBメモリにも、 それぞれ Live Ubuntu を入れておくとイザというとき便利。
ところが、 Ubuntu (公式) が公開している Live Ubuntu は exFAT からの起動に対応していない。 exFAT は FAT の後継として Microsoft が開発したファイルシステムで、 従来 4GB までのファイルしか扱うことができなかった FAT の制約が大幅に緩和されている。
昨今の動画ファイルはサイズが 4GB を超えるものも多く、 USBメモリは FAT ではなく exFAT でフォーマットしたい。 もちろん、 NTFS でフォーマットすれば大きなファイルを入れられるし、 Live Ubuntu も起動できるが、 NTFS は USBメモリには牛刀すぎる。
USBメモリは様々な機器に挿す可能性があるわけで、 NTFS にするのは躊躇してしまう。 スマホやラズパイ、 さらにはコンビニ等のプリント機など、 その全てで NTFS が問題無く使えるのだろうか? やっぱりデフォルトである exFAT のほうが安心。
Ubuntu などのインストールメディアの ISO イメージを exFAT に置いて起動する方法 (Make an exFAT Bootable USB Flash Drive) が既に公開されているが、 仕組み (Ventoy) が複雑だし、 そもそも ISO イメージを loopback デバイス経由でマウントして起動すると重くなるし、 必要なメモリ量も多いので、 利用したいとは思わなかった。 トラブった PC のスペックが低い場合など、 道具は軽ければ軽いほど好ましい。
というわけで、 exFAT でフォーマットした USBメモリに、 Live Ubuntu を入れる方法を考えてみた。 要は Live Ubuntu の initrd ファイル (cpio アーカイブ) をどう改変して exFAT に対応させるか?
基本的には Live Ubuntu の initrd を展開して exFAT に対応させる修正を行なった後、 cpio コマンドを使って initrd を作り直せばいいのだが、 initrd は複数の cpio アーカイブをつなげた形になっていて、 作り方によっては互換性の問題が起きるかも? Live Ubuntu 自身の update-initramfs コマンドを使って initrd を更新したほうが手軽だし確実。
なお、 (PC の起動に必要な) UEFI パーティションは (いまのところ) FAT でフォーマットしておいた方が無難と思われる。 ほとんど (全て?) の PC が exFAT や NTFS でフォーマットした UEFI パーティションを認識するらしいが、 最大限の互換性を求めるなら FAT にしておくべきだろう。
というわけで、 USBメモリの末尾 4MB (以下の実行例では sdc2) だけ FAT でフォーマットして UEFI パーティションとし、 残り (sdc1, ここでは 「boot パーティション」と呼ぶ) を exFAT でフォーマットする:
senri:/ # gdisk -l /dev/sdc GPT fdisk (gdisk) version 0.8.4 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Disk /dev/sdc: 121098240 sectors, 57.7 GiB Logical sector size: 512 bytes Disk identifier (GUID): 619FAAB5-5325-4404-99C4-F0541D53B069 Partition table holds up to 128 entries First usable sector is 34, last usable sector is 121098206 Partitions will be aligned on 2-sector boundaries Total free space is 0 sectors (0 bytes) Number Start (sector) End (sector) Size Code Name 1 2048 121090047 57.7 GiB 0700 Microsoft basic data 2 121090048 121098206 4.0 MiB EF00 EFI system partition 3 34 2047 1007.0 KiB EF02 BIOS boot partition senri:/ # mkfs -t fat /dev/sdc2 mkfs.fat 4.0 (2016-05-06) senri:/ # mkfs -t exfat /dev/sdc1 mkexfatfs 1.2.3 Creating... done. Flushing... done. File system created successfully. senri:/ #
UEFI パーティションは Windows ユーザ (あるいはコンビニのプリント機) からは見えないので、 boot パーティションのみを、 ふつうの USBメモリとして使うことになる。
次に grub-install コマンドで UEFI パーティションに GRUB (ブートローダ) をインストールする。 ついでに UEFI に対応していない PC (は滅多にないと思うが) でも起動できるように、 「--target i386-pc」オプションを使って MBR にも GRUB をインストールしておく。
senri:/ # mount /dev/sdc1 /mnt/usb senri:/ # mount /dev/sdc2 /mnt/efi senri:/ # grub-install --target x86_64-efi --efi-directory /mnt/efi --boot-directory=/mnt/usb/boot --removable Installing for x86_64-efi platform. Installation finished. No error reported. senri:/ # grub-install --target i386-pc --boot-directory=/mnt/usb/boot --removable /dev/sdc Installing for i386-pc platform. Installation finished. No error reported. senri:/ # blkid | grep sdc1 /dev/sdc1: UUID="E7F3-77CD" BLOCK_SIZE="512" TYPE="exfat" PTTYPE="dos" PARTLABEL="Microsoft basic data" PARTUUID="23041859-cc53-4164-be6a-44af6a966e5d" senri:/ #
UEFI パーティションに書込まれるのは GRUB コア (/EFI/BOOT/BOOTX64.EFI) のみで 124KB しかない。 UEFI パーティションは 4MB も要らないかも? GRUB 本体 (/boot/grub/x86_64-efi ディレクトリ) は boot パーティションに書込まれる。 /EFI/BOOT/BOOTX64.EFI は /boot/grub/x86_64-efi/core.efi の内容と同じ。
GRUB の設定ファイル /boot/grub/grub.cfg は ↓ こんな感じ:
set uuid="E7F3-77CD" insmod all_video menuentry "ubuntu 22.04.2 desktop amd64" { linux /casper/vmlinuz boot=casper uuid=$uuid initrd /casper/initrd }
ここで "E7F3-77CD" は USBメモリの exFAT パーティション /dev/sdc1 の UUID (Universally Unique Identifier, 汎用一意識別子)。 blkid コマンドなどで調べることができる (上記 grub-install の実行例の末尾を参照)。
/casper ディレクトリは、 Ubuntu DVD (以下の実行例では /cdrom にマウントしている) からコピーする:
senri:/ # cp -a /cdrom/casper /mnt/usb/ senri:/ # ls -la /mnt/usb/casper total 2813952 drwxr-xr-x 2 root root 32768 Feb 23 13:13 . drwxr-xr-x 4 root root 32768 Jul 3 18:10 .. -rwxr-xr-x 1 root root 59931 Feb 23 13:09 filesystem.manifest -rwxr-xr-x 1 root root 2885 Feb 23 13:09 filesystem.manifest-minimal-remove -rwxr-xr-x 1 root root 3578 Feb 23 13:09 filesystem.manifest-remove -rwxr-xr-x 1 root root 11 Feb 23 13:09 filesystem.size -rwxr-xr-x 1 root root 2731876352 Feb 23 13:09 filesystem.squashfs -rwxr-xr-x 1 root root 833 Feb 23 13:12 filesystem.squashfs.gpg -rwxr-xr-x 1 root root 137120699 Feb 23 13:09 initrd -rwxr-xr-x 1 root root 12186376 Feb 23 13:09 vmlinuz senri:/ #
filesystem.squashfs が Live Ubuntu の root ファイルシステム。 これ以外の filesystem.* は不要なので削除して構わない。 vmlinuz が Linux カーネルで、 initrd がこれから書き換える initrd ファイル。
boot パーティションが FAT 等であれば、 この状態でブータブル USBメモリとして機能するが、 exFAT だと initrd が /casper/filesystem.squashfs を見つけられず Ubuntu を起動できない。
そこで initrd の内容を書き換えて exFAT を扱えるようにする。 といっても Linux Kernel 5.4 以降は (以前の exfat-fuse ではなく) カーネルレベルで exFAT を扱うことができる。 つまり必要なのはカーネルモジュール kernel/fs/exfat/exfat.ko を initrd へ追加することだけ。
まず Ubuntu DVD を用いて Live Ubuntu を起動する (インストール DVD から起動して「Ubuntu を試す」を選択)。 /etc/initramfs-tools/modules および /usr/share/initramfs-tools/scripts/casper-helpers に以下のパッチ ubuntu.patch をあてる:
--- etc/initramfs-tools/modules~ 2023-02-23 12:59:33.000000000 +0900 +++ etc/initramfs-tools/modules 2023-07-03 08:46:22.000000000 +0900 @@ -9,3 +9,4 @@ # # raid1 # sd_mod +exfat --- usr/share/initramfs-tools/scripts/casper-helpers~ 2022-05-30 23:40:38.000000000 +0900 +++ usr/share/initramfs-tools/scripts/casper-helpers 2023-07-03 08:48:03.000000000 +0900 @@ -36,7 +36,7 @@ # FIXME: do something better like the scan of supported filesystems fstype="${1}" case ${fstype} in - vfat|iso9660|udf|ext2|ext3|ext4|btrfs|ntfs) + vfat|exfat|iso9660|udf|ext2|ext3|ext4|btrfs|ntfs) return 0 ;; esac @@ -234,7 +234,7 @@ # will cause data loss when a live CD is booted on a system # where filesystems are in use by hibernated operating systems. case "$(get_fstype ${devname})" in - vfat) + vfat|exfat) :;; *) continue;; @@ -337,7 +337,7 @@ for dev in $(subdevices "${sysblock}"); do devname=$(sys2dev "${dev}") case "$(get_fstype ${devname})" in - vfat|ext2) + vfat|exfat|ext2) :;; *) continue;; @@ -367,7 +367,7 @@ is_supported_fs(){ [ -z "${1}" ] && return 1 case ${1} in - ext2|ext3|ext4|xfs|jfs|reiserfs|vfat|ntfs|iso9660|btrfs) + ext2|ext3|ext4|xfs|jfs|reiserfs|vfat|exfat|ntfs|iso9660|btrfs) return 0 ;; esac @@ -388,6 +388,7 @@ modprobe xfs modprobe jfs modprobe vfat + modprobe exfat modprobe fuse [ "$quiet" != "y" ] && log_end_msg "...devs loaded..." touch /dev/.initramfs/lupin-waited-for-devs
この ↑ パッチでは、 起動時に (つまり initramfs で) 必要なカーネルモジュールを指定するファイル /etc/initramfs-tools/modules に 「exfat」 を追記している。 また、 initramfs 内のスクリプト 「/usr/share/initramfs-tools/scripts/casper-helpers」 を boot パーティションが exFAT でもエラーにならないよう修正している。
というか、 たったこれだけの修正で exFAT から起動できるのだから、 公式の Live Ubuntu で exFAT からの起動をサポートして欲しい。 exFAT を除外する理由でもあるのだろうか?
そして update-initramfs.distrib コマンドを使って新しい initrd を生成する。 ここで (通常の Ubuntu と同じ感覚で) update-initramfs を使ってしまうと 「update-initramfs is disabled since running on read-only media」 と言われてしまうので注意。 「read-only media」 だからダメなのではなく、 Live Ubuntu の update-initramfs は、 このメッセージを出力するだけの sh スクリプトに置き換えられている (いったい何のために?)。
例えば Live Ubuntu の Terminal を使って以下のように実行する:
root@ubuntu:/# wget https://www.gcd.org/sengoku/docs/ubuntu-22.04.2-desktop-amd64.patch --2023-07-04 01:47:50-- https://www.gcd.org/sengoku/docs/ubuntu-22.04.2-desktop-amd64.patch Resolving www.gcd.org (www.gcd.org)... 71.19.146.203, 74.207.241.21, 219.94.252.139, ... Connecting to www.gcd.org (www.gcd.org)|71.19.146.203|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1799 (1.8K) [text/plain] Saving to: ‘ubuntu-22.04.2-desktop-amd64.patch’ 2023-07-04 01:47:57 (38.1 MB/s) - ‘ubuntu-22.04.2-desktop-amd64.patch’ saved [1799/1799] root@ubuntu:/# patch -p0 < ubuntu-22.04.2-desktop-amd64.patch patching file etc/initramfs-tools/modules patching file usr/share/initramfs-tools/scripts/casper-helpers root@ubuntu:/# uname -a Linux ubuntu 5.19.0-32-generic #33~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Jan 30 17:03:34 UTC 2 x86_64 x86_64 x86_64 GNU/Linux root@ubuntu:/# update-initramfs.distrib -c -k 5.19.0-32-generic update-initramfs: Generating /boot/initrd.img-5.19.0-32-generic cryptsetup: ERROR: Couldn't resolve device /cow cryptsetup: WARNING: Couldn't determine root device W: Couldn't identify type of root file system for fsck hook root@ubuntu:/#
生成された /boot/initrd.img-5.19.0-32-generic を USBメモリの boot パーティションの /casper/initrd へコピーする。
以上で、 Ubuntu が起動できる exFAT な USBメモリができた。 ふだんは普通の USBメモリとして使える。 /casper/filesystem.squashfs は 2605MB もあるが、 いつでも Ubuntu DVD からコピーすることで元に戻せるので、 USBメモリに空きがないときは気軽に削除して構わない。