LILO "the Linux Loader" の動作について 佐野武俊 / Taketoshi Sano, (kgh12351@nifty.ne.jp) $Date: 1999/10/12 08:20:24 $, ($Revision: 1.5 $) この文書は、LILO "the Linux Loader" の動作について説明するものです。な お、対象としている LILO は ver.21 および ver.22 です。 ______________________________________________________________________ 目次 1. 起動時の動作 1.1 1st boot loader 1.2 2nd boot loader 1.3 Option linear 1.4 (New in ver 22) Option edd 1.5 その他 2. /sbin/lilo コマンドを実行した時の動作 3. 補足 3.1 この文書について 3.2 MBR 用ブートセレクタについて ______________________________________________________________________ 1. 起動時の動作 起動時に実行される LILO のコードには、1st boot loader と 2nd boot loader の 2 種類があります。 これらのコードは通常、 /boot/boot.b というファイルの中に保存されてお り、このうち 1st boot loader に相当する先頭 446bytes が "lilo" コマン ドの実行によって lilo.conf の boot= で指定された場所のブートセクターに インストールされます。このとき同時に 2nd boot loader やマップ (カーネ ル位置情報) ファイルなどのディスク上の位置を示す CHS アドレスが 1st boot loader のコード中のデータ領域に記録されます。 1st boot loader は 2nd boot loader をメモリーにロードするのが役目で す。 2nd boot loader はマップファイルをロードしてその情報を解析し、そ の結果に従ってカーネルコードをロードします。また必要な場合には initrd で使用するルートイメージのロードも 2nd boot loader が実行します。 1.1. 1st boot loader LILO によるブートでは、最初にブートセクターの先頭 446 bytes に記録され た 1st boot loader が BIOS または MBR に置かれた他のブートローダーに よってロードされます。ロードに成功し、1st boot loader が実行を開始する と最初の "L" という文字が表示されます。 次に 1st boot loader は "lilo" コマンド実行時に自分の中に記録された 2nd boot loader のディスク上の位置 (CHS セクターアドレス) を BIOS に提 示して、セクター単位で BIOS に 2nd boot loader をロードさせます。ロー ドに成功すると、コンソールに "I" という文字を表示して 2nd boot loader に制御を渡します。 lilo のソースコードで 1st boot loader に相当するのは first.S です。 (なんてわかりやすい名前でしょう!) 上記の "L", "I", の表示を実行してい るのは、それぞれ go: cli ! no interrupts mov ds,ax ! AX is already set mov es,ax ! (ES may be wrong when restarting) mov sp,#STACK ! set the stack mov ax,#STACKSEG mov ss,ax sti ! now it is safe mov al,#0x0d ! gimme a CR ... call display mov al,#0x0a ! ... an LF ... call display mov al,#0x4c ! ... an 'L' ... call display と done: mov al,#0x49 ! display an 'I' call display jmpi 0,SECONDSEG ! start the second stage loader の部分です。コメントを読めば、何をしているか想像がつきますね。 1.2. 2nd boot loader 2nd boot loader が実行を開始すると、 2 番目の "L" という文字が表示され ます。次に 2nd boot loader は、map ファイルの先頭の部分をロードしま す。ここには LILO のブートメニューで選択肢として表示されるラベルの名前 や、パスワードなどの情報が記録されています。 この先頭部分の構造は LILO のソースコードにある common.h 中で以下のよう に規定されています。 typedef struct { char name[MAX_IMAGE_NAME+1]; char password[MAX_PW+1]; unsigned short rd_size[2]; /* RAM disk size in bytes, 0 if none */ SECTOR_ADDR initrd,start; unsigned short start_page; /* page at which the kernel is loaded high, 0 if loading low */ unsigned short flags,vga_mode; } IMAGE_DESCR; (この部分に関しては ver.21, 22 とも同じ記述です。ただし、後述しますが SECTOR_ADDR の構成が 21 と 22 では違います。) このマップファイル先頭部分のロードが完了すると "O" という文字をコンソ ールに表示し、指定された待ち時間のあいだ、キー入力をチェックします。 この後、プロンプト表示やキー入力に対する処理を行い、これから起動するカ ーネルに対応したアドレスマップを上記の SECTOR_ADDR initrd,start によっ て指定された CHS セクターアドレスからロードし、このマップファイルに記 録されているカーネルや initrd ファイルのセクターアドレスを解読して、そ れぞれをロードしていきます。 これらのディスクまたはフロッピーからカーネルや initrd ファイルをメモリ ーにロードする作業は、すべてセクターアドレスを指定して BIOS に実行させ ます。 必要なセクターのロードがすべて成功した後、カーネルコードに制御を移行し て LILO は動作を完了します。 1.3. Option linear ときどき勘違いされる方がいますが、lilo.conf のパラメータに "Option linear" を追加しても、LILO のブートローダーがディスクからファイルをロ ードする時に INT13 AH=4? な Extended BIOS コールを利用するわけではあり ません。 (注: 以前はここで "option linear" を指定しても LILO のマップファイルに リニアアドレスは格納されない、と書いていたのですが ver 21 と 22 のコー ドを改めて眺めてみたところ、 ver 21 では 3bytes (=24bits) の領域にリニ アセクターアドレスを格納していたことがわかりました。また ver 22 では "option edd" が新設されこれを利用すると 4bytes (=32bits) の領域に 32bit のリニアセクターアドレスを格納し、かつ起動時には Extneded BIOS Call を利用する、という動作になるようです。) このオプションは、マザーボードの BIOS が認識するディスクのジオメトリと Linux カーネルの認識するジオメトリが互いに異なる場合、LILO の使うマッ プファイルにはリニアセクターアドレスを保存しておいて、起動時に「BIOS が認識するディスクのジオメトリ」を基準とした CHS セクターアドレスに換 算し、このアドレスを BIOS に渡してディスクから必要なセクターをロードす るという動作を指定するものです。 このオプションを指定しても、LILO が「1023 シリンダ」を超える領域にアク セスすることは不可能ですので、御注意下さい。 1.4. (New in ver 22) Option edd このオプションは LILO 22 で新設されたもののようです。CHANGES によれば Enhanced Disk Drive Support が有効な Extended BIOS のためのもの、との こと。 マザーボードもディスクドライブも最近のもので、どうしても 1023 シリンダ の壁を超えて起動させたい場合には、試してみると良いかも。 1.5. その他 ちなみに、詳細はまたいつか追加して書くつもりですが Linux カーネルの先 頭 512bytes はカーネルが自前で持っているブートローダーであり、 "make zdisk" で作成したブートフロッピーからの起動ではこれが使われます。 この自前のブートローダーは i386 系の場合 カーネルソースツリーの arch/i386/boot/bootsect.S にあります。 LILO や LOADLIN からの起動では、カーネルのロードが完了するとこの部分 (bootsect) を飛ばして次の setup.S や video.S のコードに制御を移行しま す。 CPU の動作を 16bit モードから 32bit モードに移行するのは setup.S の中で実行しています。 これらの実行が終わると次に arch/i386/boot/compressed/head.S が実行され ます。こちらは最初から 32bit モードで実行されることを前提としたコード になっています。この head.S の中にある decompress_kernel() が圧縮され たカーネル本体を展開します。 head.S の実行は展開されたカーネル本体に制 御を渡して完了します。 2. /sbin/lilo コマンドを実行した時の動作 "lilo" コマンドは別名 map creator (マップ作成ツール) と呼ばれており、 その主な機能は設定ファイル lilo.conf の解読と、その中の指定およびコマ ンドライン (オプション) による指定に従って bootloader が起動時に使用す るマップファイルを作成し、その中に必要な Map Descriptor Table を適切に 記録することです。 通常 "lilo" コマンドは lilo.conf を解読して、使用するカーネルごとに指 定された Image ファイル (および、もしあれば initrd ファイル) に対する CHS セクターアドレスを取得し、それを起動時に使用する Map Descriptor Table のデータ型式にしてマップファイルに保存します。 "lilo" コマンドでファイルからセクターアドレスを調べる部分は geometry.c の geo_find() にあります。 "lilo" コマンドに -v オプションを複数重ねて起動すると、マップ作成に使 用されたセクターアドレスを観察することができます。 もし Image= で指定したファイルがマウントされていないファイルシステム上 にあると、"lilo" コマンドはそのファイルに対するセクターアドレスを調べ ることができずにエラーを出します。 なお、起動時に使用する 2nd boot loader のセクターアドレスを 1st boot loader のコード中に書き込むのも "lilo" コマンドの仕事です。 3. 補足 3.1. この文書について Linux 用のブートローダーとして、この "lilo" を使う場合が多いのですが、 マニュアルでエラーメッセージの意味を確認する際など、動作を理解しておく ときっと役に立つだろうと思ってこの文書を作成しました。 内容についてはできる限り正確を期したつもりですが、まだまだ間違いや誤解 している個所などあるかもしれません。この文書に対する御意見、御感想、間 違いの指摘などありましたら、著者または JF project まで御一報頂ければさ いわいです。 なお、この文書の配布等については GPL2 に従うものとします。 3.2. MBR 用ブートセレクタについて 個人的な好みですが、"lilo" のインストール先は MBR (Master Boot Record, ハードディスク先頭のブートセクタ) よりも Linux システムのルートパー ティションのほうが適していると思います。ハードディスクの MBR にはより 一般的なブートセレクタ、たとえば os-bs, bteasy, extIPL, btsel などをイ ンストールしたほうがトラブルが起きた時の対応などを考慮するとより安心で きます。 この中でも特に個人的なお薦めは extIPL です。最近、バージョンアップして 拡張領域内の論理領域からも起動可能になりました。またソース公開であり、 かつ Linux 上で make できる (gcc + nasm) 点も見逃せないポイントです。