玩式草子─ソフトウェアとたわむれる日々

第93回 xorrisoとUEFIブート再び[その3]

この記事を読むのに必要な時間:およそ 6 分

xorrisofsとBIOS/UEFIデュアルブート

さて,最後に筆者がxorrisoを調べるきっかけになった,DVD/USBメモリそれぞれのBIOS/UEFIのデュアルブートの話題を取りあげましょう。

xorrisoを取り上げた最初の回にも触れたように,筆者がこのソフトウェアを使うようになったきっかけは,mkisofs/cdrecordでは実現できなかった「DVDイメージをそのままUSBメモリにベタ書きしてもUEFIから起動できる」という機能を,Arch Linuxのインストーラが実現していたからでした。

たとえば,Arch Linuxのインストール用ISOの再構成方法を紹介したページ"Remastering the Install ISO"を見ると,このようなコマンドラインを使ってISOイメージを生成しています。

$ iso_label="ARCH_201209"
$ xorriso -as mkisofs \
     -iso-level 3 \  
     -full-iso9660-filenames \
     -volid "${iso_label}" \
     -eltorito-boot isolinux/isolinux.bin \
     -eltorito-catalog isolinux/boot.cat \
     -no-emul-boot -boot-load-size 4 -boot-info-table \
     -isohybrid-mbr ~/customiso/isolinux/isohdpfx.bin \
     -eltorito-alt-boot -e EFI/archiso/efiboot.img \
     -no-emul-boot -isohybrid-gpt-basdat \
     -output arch-custom.iso \ 
     ~/customiso

一方,以前紹介したように,Plamo Linuxのインストール用ISOイメージは,mkisofsを使って以下のようなコマンドラインにしていました。

$ mkisofs -v -J -r -b isolinux/isolinux.bin -c isolinux/boot.cat \
    -no-emul-boot -boot-load-size 4 -boot-info-table \
    -eltorito-alt-boot  -eltorito-platform efi -eltorito-boot isolinux/efiboot.img \
    -V UEFI-test -o UEFI-test.iso DVD_contents

xorrirsoのコマンドラインは最初に"-as mkisofs"を指定しているので,オプション等はmkisofsと同等になるはずですが,両者を見比べてみると,xorrisoには"-isohybrid-mbr","-isohybrid-gpt-basdat"といったmkisofsには存在しないオプションが追加されています。そこで,これらのオプションの意味を調べてみました。

まず,これらオプションの名前になっているisohybridという機能について紹介しておきましょう。"isohybrid"はCD/DVDからLinuxを起動する際に使われるisolinuxの一機能で,"isolinux"はその名の通りISO9660ファイルシステムからLinuxを起動するためのブートローダです。

上記使用例にあるように,mkisofsで"-b isolinux/isolinux.bin"を指定すると,あらかじめisolinuxディレクトリに用意されているisolinux.binが,ブートローダとしてISOファイルのシステム領域に書き込まれます。

起動メディアがCD/DVDだった場合,PCのBIOSは起動処理をISOファイルのシステム領域にゆだねるので,そこに用意されたisolinux.binが実行され,カーネルなど必要なファイルを読み込みます。

一方,このISOファイルをUSBメモリ等にベタ書きした場合,書きこまれた内容はISOファイルであっても,ハードウェアとしてのUSBメモリはBIOSからはHDDとして見えます。その結果,BIOSはisolinuxのあるISO9660のシステム領域ではなく,HDD(USBメモリ)の先頭にあるMBRに起動処理をゆだねようとするので,そのままではisolinuxが起動できません。

isohybridはこの間を繋ぐための開発されたツールで,isolinuxで起動するように作成したISOファイルの先頭部分に,isolinuxを呼び出すための擬似的なMBRを書き込みます。

この処理を施したISOファイルをベタ書きしたUSBメモリから起動すると,BIOSはUSBメモリをHDDと見なして擬似的なMBRを呼び出し,擬似的なMBRがisolinuxを起動して実際のカーネル等を読み込む,という2段ロケットのような方法でシステムが起動されることになります。

擬似的なMBRはISOファイルの未使用領域に書き込まれるので,CD/DVDから起動する際には読み飛ばされ,動作に影響は生じません。

mkisofsを使っていたPlamo Linuxの場合,isohybrid処理はsyslinuxパッケージから提供されているisohybridというコマンドを使って,mkisofsで作成したISOファイルへの後処理として行っていました。

一方,xorriroの場合,syslinuxとの親和性が高まっていて,ISOイメージを作成する際に直接擬似的なMBRを書き込んでしまうことが可能です。そのためのオプションが-isohybrid-mbrで,上記Arch Linuxのコマンドラインでは"~/customiso/isolinux/isohdpfx.bin"を擬似的なMBRとしてISOファイルに埋めこんでいます。

擬似的なMBRは単純に書き込むだけではだめで,MBRから呼び出すisolinux.binの位置を,作成したISOファイルに合わせて登録する必要があります。そのためisohybridコマンドは作成済みのISOファイルへの後処理用のツールとして開発されたのに対し,xorrisoでは一歩進んでisohybridの機能を自らのうちに取り込んでいるわけです。

もう一つ-isohybrid-gpt-basdatもmkisofsにはないxorrisoの独自機能で,EFI用に用意されたブートイメージを"Basic Data"タイプの仮想的なGPTパーティションとしてパーティションテーブルに登録する,という処理を行います。

言葉で説明するだけではわかりにくいと思うので,このオプションがどう働くのか,具体的な例で紹介しましょう。

まず,Plamo Linux用に用意しているBIOSとUEFI用のブートローダをTestディレクトリにコピーしておきます。具体的には,UEFI用のブートローダを収めたEFIディレクトリとそのディレクトリをFAT16なファイルシステムに収めたefiboot.img,BIOS用のisolinux用のディレクトリを用意します。これらのファイルの意味や作り方については,本連載の過去記事を参照してください。

$ ls -R Test
Test:
EFI/  efiboot.img  isolinux/

Test/EFI:
BOOT/

Test/EFI/BOOT:
BOOTx64.efi  bootia32.efi  grub.cfg

Test/isolinux:
System.map  config       initrd.gz     isolinux.cfg  libcom32.c32  plamo41.lss  sample.msg    vmlinuz
boot.cat    efiboot.img  isolinux.bin  ldlinux.c32   libutil.c32   plamo61.lss  vesamenu.c32

このディレクトリからxorrisoを使って起動可能なISOファイルを作ります。

$ xorriso -as mkisofs -o test01.iso \
    -isohybrid-mbr /usr/share/syslinux/isohdpfx.bin \
    -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table \
    -eltorito-alt-boot -e efiboot.img -no-emul-boot Test

GNU xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.

Drive current: -outdev 'stdio:test01.iso'
Media current: stdio file, overwriteable
...

もう1つ,オプションに"-isohybrid-gpt-basdat"を追加したISOファイルを作ってみます。

$ xorriso -as mkisofs -o test02.iso \
    -isohybrid-mbr /usr/share/syslinux/isohdpfx.bin \
    -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table \
    -eltorito-alt-boot -e efiboot.img -no-emul-boot -isohybrid-gpt-basdat Test

GNU xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.

Drive current: -outdev 'stdio:test02.iso'
...

作成された2つのISOファイルのサイズは同じです。

$ ls -l test01.iso test02.iso 
-rw-r--r-- 1 kojima users 128,974,848  7月 10日  14:28 test01.iso
-rw-r--r-- 1 kojima users 128,974,848  7月 10日  14:31 test02.iso

一方,これらをfileコマンドで比べると,パーティションの表示が異なっていることに気づきます。

$ file test0[12].iso
test01.iso: DOS/MBR boot sector ISO 9660 CD-ROM filesystem data 'ISOIMAGE' (bootable); partition 1 : ID=0x17, active, start-CHS (0x0,0,1), end-CHS (0x7a,63,32), startsector 0, 251904 sectors
test02.iso: DOS/MBR boot sector ISO 9660 CD-ROM filesystem data 'ISOIMAGE' (bootable); partition 2 : ID=0xef, start-CHS (0x3ff,254,63), end-CHS (0x3ff,254,63), startsector 136, 65536 sectors

ISOファイルは一種のファイルシステムなので,fdiskを使って内部構造を調べることもできます。

$ /sbin/fdisk -l test01.iso
ディスク test01.iso: 123 MiB, 128974848 バイト, 251904 セクタ
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
...
デバイス    起動 開始位置   最後から セクタ サイズ Id タイプ
test01.iso1 *           0   251903 251904   123M 17 隠し HPFS/NTFS

$ /sbin/fdisk -l test02.iso 
ディスク test02.iso: 123 MiB, 128974848 バイト, 251904 セクタ
...
デバイス    起動 開始位置   最後から セクタ サイズ Id タイプ
test02.iso1 *           0   251903 251904   123M  0 空
test02.iso2           136    65671  65536    32M ef EFI (FAT-12/16/32)

この結果を見ると,-isohybrid-gpt-basdatオプションを指定した場合,ISOファイルの中に用意したefiboot.imgの領域(セクタで言えば136から65671)が,ESP(EFIシステムパーティション)としてパーティションテーブルに登録されていることがわかります。

この領域は実際にはISOファイルの一部なわけですが,仮想的なパーティションとしてパーティションテーブルに登録することで,UEFIにESPと思いこませ,そこにあるブートローダを起動させているわけです。

本来,ISOファイルにはパーティションテーブルは不要なので,このISOファイルをDVD等に書き込んで起動した場合,パーティションテーブルの部分は無視されます。

一方,ISOファイルをUSBメモリにベタ書きしUEFI環境でブートすると,USBメモリはHDDとして認識されるためHDDブートの処理が行なわれ,UEFIはパーティションテーブルを利用してブートローダを探すことになります。

これらの流れを整理してみましょう。

従来のPC BIOSから起動する場合,起動メディアがDVDならば,ISO9660の流儀に則ってisolinuxが実行されます。一方,起動メディアがISOイメージをベタ書きしたUSBメモリの場合,"-isohybrid-mbr"オプションでISOイメージの先頭に書き込まれた疑似MBR(isohdpfx.bin)が起動され,ここからisolinuxが呼び出されます。

一方,UEFI環境では,起動メディアがDVDの場合,UEFIはDVDを読み込んでそのディレクトリを調べ,EFIディレクトリにある/BOOT/BOOTx64.efiを起動します。起動メディアがUSBメモリの場合,UEFIはUSBメモリをHDDと認識してパーティションテーブルを探し,"-isohybrid-gtp-basdat"で作成した仮想ESPを読み込んで,そこにある/BOOT/BOOTx64.efiを起動します。

ISOファイルの先頭部分には未使用領域があることを利用して,そこに疑似MBRと仮想パーティションテーブルを用意すれば,1つのISOファイルでDVDとUSBメモリ,さらにはPC BIOSとUEFIを使いわけてブートできる,このテクニックに気付いた時は,優れたミステリーを読み終えた時のような興奮を覚えました。


以前触れたように,mkisofsを使っていたころは,⁠ISOイメージをベタ書きしたUSBメモリからUEFI起動できない」という問題が気になっていました。

今回,xorrisoをイジってみて,このトラブルの原因は,ISOイメージにESPを登録したパーティションテーブルが存在していなかったからだ,とわかり,長年ひっかかっていたトゲがやっと抜けたような気分になりました(苦笑⁠⁠。

ソフトウェアの世界では,この種の「コロンブスの卵」的なアイデアやテクニックはあちこちに隠れています。ドキュメントやソースコードを手掛りにそれらを読み解いていくのも,フリーソフトウェアの魅力のひとつと言えるでしょう。

著者プロフィール

こじまみつひろ

Plamo Linuxとりまとめ役。もともとは人類学的にハッカー文化を研究しようとしていたものの,いつの間にかミイラ取りがミイラになってOSSの世界にどっぷりと漬かってしまいました。最近は田舎に隠棲して半農半自営な生活をしながらソフトウェアと戯れています。

URLhttp://www.linet.gr.jp/~kojima/Plamo/index.html