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

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

前回までにxorrisoのさまざまな機能を紹介してきました。紹介したのはxorrisoの機能のごく一部にすぎないものの、xorrisoの実力とISO9660ファイルシステムの持つ可能性を感じていただけたと思います。

xorrisoはこのように強力なソフトウェアなものの、機能が豊富すぎて(その結果ドキュメントも長大で⁠⁠、初心者が手を出すにはやや敷居が高くなっています。

また、オプションの指定方法や意味等がLinuxでCD/DVDを作成する際のデファクト・スタンダートと言えるmkisofsやcdrecordと大きく異なってることも、xorrisoが敬遠される一因でしょう。

作者もそのあたりは気になったようで、xorrisoにはmkisofs/cdrecordとほぼ同じオプションが使えるエミュレーション機能が用意されています。今回はこのエミューレション機能と筆者がxorrisoを使うきっかけとなったBIOS/UEFIデュアルブートの話題を紹介しましょう。

xorrisoのエミュレーション機能

xorrisoには-as <personality>という指定で、<personality>に指定したコマンドをエミュレートする機能があります。<personality>にはmkisofscdrecordが指定でき、"mkisofs"を指定するとmkisofsのオプション体系が、"cdrecord"を指定するとcdrecordのオプション体系が、それぞれ利用可能になります。

xorrisoのmanページからこの機能を紹介した部分を引いてみましょう。参考のために私訳も付しておきます。

Command compatibility emulations:

     Writing of ISO 9660 on CD is traditionally done by program  mkisofs  as
     ISO 9660 image producer and cdrecord as burn program.  xorriso does not
     strive for their comprehensive emulation.  Nevertheless it is ready  to
     perform  some of its core tasks under control of commands which in said
     programs trigger comparable actions.

     -as personality option [options] --
            Perform the variable length option list as sparse  emulation  of
            the program depicted by the personality word.

互換コマンド用エミュレーション

CDにISO9660を書き込むには、従来、ISO9660イメージ作成用のmkisofsと書き込み用のcdrecordが使われてきた。xorrisoは、それらコマンドを包括的にエミュレーションするわけではないが、主要な機能に関しては、それらコマンドが使用するオプションと共に利用可能になっている。

-as personality option [options] --

personalityとして指定したプログラムに、可変長のリストとして指定されたオプションを与えた際の処理をおおまかに模倣する。

すなわち、"xorriso -as mkisofs"とすると、mkisofsと同じオプションが使えるというわけです。指定可能なオプションは"-help"で一覧することができます。

$ xorriso -as mkisofs -help
  Usage: xorriso -as mkisofs [options] file...
  Note: This is not mkisofs. See xorriso -help, xorriso -version, man xorrisofs
  Options:
    -f, -follow-links           Follow symbolic links
    -graft-points               Allow to use graft points for filenames
    -help                       Print option help
    -hfsplus                    Generate HFS+ filesystem
    -hfsplus-file-creator-type CREATOR TYPE iso_rr_path
                                Attach creator and type to a File
...

この結果を"mkisofs -help"で表示されるmkisofsのオプション一覧と比較してみると、manページでsparse emulationと称しているとおり、両者はおおまかにしか重なりません。しかし、RockRidge形式を使うための"-R"、Joliet形式を使うための"-J"、出力先を指定する"-o"、ボリュームIDを指定する"-V"、起動処理回りの"-no-mul-boot","-eltorito-alt-boot"等、よく使う重要なオプションはカバーされており、普通に使う範囲では問題なさそうです。

事実、以前mkisofsを取り上げた回で紹介した実行例は"xorriso -as mkisofs ..."で対応できました。

この"-as <personality>"には、<personality>のコマンド名でxorrisoを起動すると自動的に有効になるというショートカットも用意されています。すなわち、mkisofsという名前でxorrisoへのシンボリックリンクを張り、xorrisoをmkisofsという名前で起動すると、自動的に"-as mkisofs"オプションが指定されたことになるわけです。

エミュレーション機能でもうひとつ重要なpersonalityがcdrecordです。

$ xorriso -as cdrecord -help
GNU xorriso 1.4.6 : RockRidge filesystem manipulator, libburnia project.

Usage: xorriso -as cdrecord [options|source_addresses]
Note: This is not cdrecord. See xorriso -help, xorriso -version, man xorrecord
Options:
        -version        print version information and exit emulation
        --devices       print list of available MMC drives and exit emulation
        dev=target      pseudo-SCSI target to use as CD-Recorder
        drive_scsi_dev_family=sr|scd|sg         select Linux device type
        -v              increment verbose level by one
        -V              increment SCSI command transport verbose level by one
        -checkdrive     check if a driver for the drive is present
        -inq            do an inquiry for the drive
...

こちらの方もcdrecordの主要な機能のみをカバーしている程度ですが、⁠mkisofsで作成したISOイメージをcdrecordで書き込む」という使い方の範囲は十分対応できます。また、このオプションもシンボリックリンクを利用してcdrecordという名前でxorrisoを起動すれば、自動的に有効になります。

エミュレーション機能を使えば、xorriso独自の機能を学ばなくても、従来通りのmkisofs/cdrecordのつもりでxorrisoを使うことができます。しかしながら、前回までに紹介してきたように、xorrisoにはISO9660ファイルシステムを自在に操作する便利な機能があるので、ぜひそれらも使いこなせるようになってください。

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段ロケットのような方法でシステムが起動されることになります。

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を登録したパーティションテーブルが存在していなかったからだ、とわかり、長年ひっかかっていたトゲがやっと抜けたような気分になりました(苦笑⁠⁠。

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

おすすめ記事

記事・ニュース一覧