syslinuxを使ってUEFIで起動するUSBメモリ

Linuxのブートローダといえば今はgrubが多い。EFI対応のgrubもあって設定項目も豊富で動的にパラメータを変更できるのも良い。ただ複雑でややこしい。それにひとたびブートローダが状態を見失うと復帰が結構めんどい。

それに比較してsyslinuxは軽量で、本体は数個のファイルだけでextだけでなくFATやPXEにも置けるし、liloみたいに面倒もないし、個人的にはブートローダとしての理にかなっていると思う。それに最近はUEFIもごく一般的になってるので、重量級で高機能なブートローダって要らない気がする。

で、UEFIを今まで理解しないまま来てしまったので、ブートローダをレガシーなMBRのgrubからUEFIなsyslinuxに変えてみるテスト。実験用環境はUbuntu desktop 10.04TLSが動くものを用意。PCは何台か試したが、Intel ComputeStick以外はすべて64ビットUEFIだった。ComputeStickも設定変更で64ビットUEFIになる。どうやらATOMマシンのうちWin8.1を動かしたいものは32ビットUEFIが標準っぽい。UEFIのビット数は起動したいOSのそれと同じにする必要がある。64ビットUEFIのシステムは32ビットのWindowsやi386なLinuxは起動しない。ここでは64ビットUEFIシステムのみを対象とした。

1.USBメモリを用意

適当なUSBメモリをFAT16かFAT32でフォーマットし、/EFI/BOOT ディレクトリと /linux ディレクトリを作成。パーティション無しのスーパーフロッピー形式、MBR形式でフルに1パーティションどちらでも良い気がするが、MBR形式1パーティションのが安全な気がする。

.

2.syslinuxをダウンロード

http://www.syslinux.org/wiki/index.php/Download からリンクをたどって
https://www.kernel.org/pub/linux/utils/boot/syslinux/ のsyslinux-6.03.zip を落とす。

.

3.64ビットUEFI用のsyslinuxのファイルをUSBメモリに配置

syslinux-6.03.zip の中から syslinux.efi 、ldlinux.e64 を取り出してUSBメモリに置く。
(syslinux)/efi64/efi/syslinux.efi を (USB)/EFI/BOOT/bootx64.efi にリネームコピー、
(syslinux)/efi64/com32/ldlinux.e64を (USB)/EFI/BOOT/ にそのままコピー、

.
4.LinuxカーネルをUSBメモリに配置
実働環境の (ubuntu)/boot/ から vmlinuz と initrd をUSBメモリの適当なところに持ってくる。

(ubuntu)/boot/vmlinuz-3.19.0-25-generic を (USB)/linux にコピー。
(ubuntu)/boot/initrd.img-3.13.0-65-generic を (USB)/linux にコピー。

※ここでは /linux にしたがsyslinux.cfgで指定するのでEFIパーティション内ならどこでも良い。/boot や /EFI/boot に置きたい人もいるだろう。その場合はsyslinux.cfgを合わせて変更すること。現行のsyslinuxでは別パーティションのファイルは参照できないので注意。将来はできるようになるかもしれない。

.
5.設定ファイルを作成
次のような内容で(USB)/EFI/BOOT/syslinux.cfg を作成。UUIDは適当なので、実際は実働環境の /dev/disk/by-uuid とかを確認する。syslinux.cfgは (USB)/EFI/boot/syslinux/ とか (USB)/ とか (USB)/syslinux/ に置いても良いはず。読みに行く順番があるので複数置くと最初に読まれたものだけが処理される。

## syslinux.cfg ここから ##

SAY uefi syslinux config
PROMPT 1
TIMEOUT 30
DEFAULT linux64

LABEL linux64
KERNEL /linux/vmlinuz-3.13.0-65-generic
APPEND ro initrd=/linux/initrd.img-3.13.0-65-generic root=UUID=00183394-08dc-4c70-bfad-57af39255555

## ここまで ##

※UUIDの値は cat /proc/cmdline とか /dev/disk/by-uuid/* とかを参考にする。

終わり。

ここまでで、USBメモリのファイル構成は次のようになる。
(USB)
/EFI/BOOT/bootx64.efi     ← 64ビットUEFI用のsyslinux.efiをリネームしたもの
/EFI/BOOT/ldlinux.e64     ← 64ビットUEFI用のsyslinuxに入っているものそのまま
/EFI/BOOT/syslinux.cfg    ←環境にあわせて作るテキストファイル
/linux/vmlinuz-3.19.0-25-generic     ←動いている環境から持ってきたカーネルイメージ
/linux/initrd.img-3.13.0-65-generic   ←動いている環境から持ってきた初期RAMディスクイメージ

あとはこのUSBメモリをPCに差し込んで起動するだけ。PCのBIOS設定でBOOT方法でUEFIを使うようにしておくこと。Linuxの本体(ルートファイルシステム)が入っていないとinitrdの途中で止まるが、USBメモリから起動できることは確認できる。ここまで確認できれば後はsyslinuxのモジュールを追加したりLinuxの起動パラメータを変更して本体が動くようにしたりできると思う。起動順序は解説無しでもわかると思うくらい簡単で、

1.UEFIが/EFI/BOOT/bootx64.efiを見つけるとそれを読み込んで実行。
2.bootx64.efiはsyslinux本体なのでそれが同じところにあるldlinux.e64を読み込んで
3.syslinux.cfgを同じディレクトリに見つけるので解釈して実行。
4.syslinux.cfgにはカーネルとRAMディスクのイメージの場所が書いてあるので
それらを読み込んでシステム起動。

非常にシンプルで良い。ここで重要なのはUEFIが読みにいくファイル名が /UEFI/BOOT/bootx64.efi であることと、syslinux.efi(bootx64.efi)がldlinux.e64を必要としていること。

ここまでの手順で勘が良い人ならWindowsのインストールディスクからFAT32でフォーマットしたUSBメモリにファイルをコピーするだけでUSB起動メディアができる理由が分かると思う。UEFIではMBR形式で必須の起動可能フラグとかブートセクタとかIPLとか要らない ので、MBRでもUEFIでもどちらでも起動できるようにするというのでなければ不要。 UEFI的にはあたりまえとはいえ、知らない人もまだまだ多い。(UEFI起動したいだけなのにブートセクタを作る手順を含めて紹介してるものを結構見かける)

UEFIブートに関してisolinuxのほかに、efilinuxでも成功しているのだけどUbuntuのパッケージで入れるとなぜか動かなくてソースからビルドする必要があるのと/EFI/BOOT/startup.nshから起動するためにUEFI Shellが必要なので手順がかなり異なる。これについては後日掲載予定。

ちなみにUEFI用のsyslinuxからは他のUEFIアプリケーションを起動できない。いったんsyslinuxが起動したらUEFIアプリをチェインロードすることはできないので他OSとのマルチブートはUEFIシェルでスクリプトを組むかUEFIアプリをロードできるローダーで処理することになる。

はっきり書かれていた。将来UEFIアプリのロードがサポートされるといいな。
http://bugzilla.syslinux.org/show_bug.cgi?id=17

Keshav Amburay 2013-07-21 19:59:07 EDT

Syslinux 6.01 (and 6.02-preXX) do not support chainloading (U)EFI 
applications in efi64 or efi32 build. The shipped chain.c32 module 
contains code only for chainloading BIOS boot-sectors and is 
currently useless in (U)EFI systems.