ブート
ブート(boot)またはブートストラップ(bootstrap)は、コンピュータシステムの電源投入時、あるいはシステムのリセット後、モニタやOSなどなんらかの基本的なシステムソフトウェアを主記憶に展開し、ユーザプログラムを実行できるようにするまでの処理の流れをいう。ブートローダ(boot loader)は、以上のプロセスで使われるローダ、すなわち不揮発性の補助記憶にある目的のプログラムを読み出し、揮発性の主記憶に書き込むプログラムのことである。
電源投入時のブートのことを「コールドブート」、リセットされたことによるブートを「ウォームブート」という。ウォームブートでは、コールドブートにおける最初のほうの手続きのいくつかが必要無い場合もあり、そういった手続きを省略することもある。
ブートストラップまたはブートストラップローダ(bootstrap loader)という名前は、ブーツのつまみ革(strap)を自分で引っ張って自分を持ち上げようとするイメージから来ている。つまり、コンピュータはプログラムをロードしないと動作できないが、プログラムをロードするプログラムはどうロードするのだ? というパラドックスに着目した呼称である。
初期の電子計算機のひとつであるENIACは、いわゆるノイマン型コンピュータではなく、プログラムはパッチボードを利用した配線によっておこなわれ、また解決したい問題の計算式の初期値などを最初から設定して計算を行うような計算機であった。
ノイマン型として実用的に稼働したとされる初期のコンピュータのEDSAC(1949年稼働)では、イニシャルオーダ (initial orders) と呼ばれたプログラムが、ロータリースイッチで実現された一種のROMからハードウェア的に主記憶に書き込まれる。イニシャルオーダは非常に技巧的なわずか数十語のコードで単純ながらアセンブラ的機能を実現しており、紙テープを読み込んでそれを機械語に変換し主記憶の残りの部分に書き込む(英語版WikipediaのEDSAC#System_softwareを参照)。EDSACのプログラム技法は成書「The Preparation of Programs for an Electronic Digital Computer」として広まり、パラメトロンコンピュータPC-1他のイニシャルオーダ (イニシャルインプットルーチンとも) がEDSACのイニシャルオーダの影響を受けて作成された。
EDSACの技法は成書として公刊されたため、同様のローダーがこの時代の多くのコンピュータで開発・使用されたが、そのローダをどうロードするか、という点では各種の手法があった。当時はそれらのうちの1つの手法を「ブートストラップ方式」と呼んでいた。ILLIAC Iの方式がブートストラップである。
1950年代の IBM 701 以降、何らかのブート処理でプログラムやOSを主記憶にロードするようになった。IBMのメインフレームではこれを "Initial Program Load" と称している。Load Card、Load Tape、Load Drum などと表示されたボタンを押下するとハードウェアの論理回路が対応する周辺機器からブートプログラムを読み込み、それを実行する。するとブートプログラムがより大きなプログラムを自動的にロードする。「ブート」という言葉は1958年からこの意味で使われている。
言葉の歴史としては、自分自身で自分のための土台を用意する、といったような意味では、電子回路の分野にもブートストラップという手法がある。またロバート・A・ハインラインの1941年の中篇SFの題By His Bootstrapsも、そのような意味でブートストラップという語を使っている。
DEC PDP-8 以降のミニコンピュータでは、フロントパネルにあるスイッチ群を操作して短いプログラムを入力する方法が採用された。初期のミニコンピュータは磁気コアメモリを使っており、電源を切っても情報は失われない。従ってブートローダーは消去されない限りメモリ上に存在し続けるが、バグのあるプログラムを実行して全メモリの内容を上書きしてしまうこともある。PDP-11でも同様の手法を採用したが、後にDECはオプションで32ワード(64バイト)のブートプログラムを格納したROMを追加できるようにした。このROMは集積回路ではなく、M792というUnibus用カードであり、32×16のダイオードアレイで回路を構成している。ダイオードが通電する部分のビットは1になり、通電しないようダイオードを除くと対応するビットが0になる。DECは様々な周辺機器からのブートに対応するため、同様のカードを BM792-Yx シリーズとして販売した。
IBM 701 (1952–1956) には "load" ボタンがあり、それによってパンチカード、磁気テープ、磁気ドラム装置のいずれかから先頭の36ビットワードを読み込む。そのうち先頭の18ビットは命令として実行され、通常はメモリに追加のワード群を読み込む命令になっている。IBM 1401 (1958) では同様にパンチカードリーダーからプログラムをロードする。80文字が格納されたパンチカードの内容は 001 から 080 番地のメモリに読み込まれ、001番地から命令として実行開始する。命令は通常いつも同じで、この先頭80文字分の情報をアセンブリエリアに転送し、2枚目以降のパンチカードの内容を読み込んでプログラムを構成する。アセンブリエリアに転送し終わると、080 番地の命令へジャンプし、そこにある命令(カードを読み込む命令)を実行することで、次のパンチカードを読み込み、その情報を処理する。つまり、パンチカード1枚ずつが次のパンチカードをブートストラップする形になっている。
CDC 6600 (1964) には144個のトグルスイッチを備えた dead start と呼ばれるパネルがある。このパネルで12ワードの情報を0番の周辺プロセッサ (PP0) のメモリに転送する。それを命令列として実行することでPP0は自身のメモリに必要なコードをロードし、他のPPを初期化する。
GE 645 (1965) には "BOOT" ボタンがある。
Multics (1967) にはブートコマンドがあった。
UNIXでは、The Unix Programmer's Manual 第1版(1971年11月3日)に "boot" への言及がある。
1975年、CSELTの研究者であるアルベルト・チャラメッラは、電話交換機のコンピュータをブートするデバイスの特許を取得した。ブートローダは、現代のROMメモリに常駐し、ブートプロセスはシングルボタン押下で起動した。デバイスは、アドオン(例PDP-11用)などの任意の種類のコンピュータに適していた。
以上で述べたような古い時代において、電源投入直後の機能があれこれと話題になったことには、いくつかの原因がある。
古いコンピュータは、
メモリ空間が狭いことが多く、その空間を少しでも自由に使える主記憶のRAMに当てたい
ROMにあたる記憶装置が特殊な装置であったりして容量も少なく、また主記憶と同様に読み出しができるものではなかった
等の理由から、この過程を技巧的なブートシーケンスにせざるをえなかったのである。
集積回路によるROM、具体的にはマスクROM、PROM、EPROM、フラッシュメモリの時代になると、以上のような制限はかなり緩和され、ファームウェアとしてメモリ空間の一部にブートプログラムを存在させ、電源投入後やリセット後、プロセッサは単にそのアドレスから実行を始めればよい、というようになった。その結果、一般的なユーザのブート時の関心事は、ハードディスク上のファイルシステムにあるOSを、どうロードして実行するか、というような点に移った。組込みシステムやゲーム機などでは、最初からROMに実行イメージを展開しておき、ブートしたらそのまま目的のシステムが実行される、というような形態もある。
Appleの最初のコンピュータ Apple I (1976) にはPROMチップが搭載されていたため、フロントパネルが不要になった。当時の広告では "No More Switches, No More Lights ... the firmware in PROMS enables you to enter, display and debug programs (all in hex) from the keyboard."(スイッチはいらない、ライトもいらない…PROM内のファームウェアで、キーボードからプログラムを入力し、表示し、デバッグできる)と宣伝している。これはそれ以前の Altair 8800 などに対比してアピールしているのである。
Atari ST などのホームコンピュータは、電源を入れるとROM上のOSがすぐさま起動する。そのため、二次記憶装置からOSをロードする機能が省かれている。システムのカスタマイズやアクセサリ、サポートソフトウェアなどはフロッピードライブからブート時に自動的にロードされる。電源投入から一定時間フロッピーがセットされない場合やフロッピー内に追加コンポーネントが見つからない場合、それらのロード処理はタイムアウトする。これによりブランクディスク挿入を防ぐ。
多くのコンピュータシステムでは、メインメモリ上の実行コードだけを実行できる。しかし、最近のオペレーティングシステムはハードディスクドライブやLive CD、フラッシュメモリ(USBメモリなど)に格納されている。つまり、コンピュータの電源を入れた直後、メモリ上にはオペレーティングシステムは存在しない。コンピュータのハードウェアだけではオペレーティングシステムがやっているような複雑なことはできないので、ディスクから任意のプログラムをロードするというようなことはできない。ここで『オペレーティングシステムをメモリにロードするためには、オペレーティングシステムがメモリに存在していなければならない』というジレンマが生じる。
このパラドックスの解決法は、ブートローダ(またはブートストラップローダ)と呼ばれるROM上にある特殊な小さいプログラムを使うことである。このプログラムはオペレーティングシステムの全ての機能を持っているわけではないが、オペレーティングシステムをロードして起動するための別のプログラムをロードするには十分な機能を持っている。多段階のブートローダがよく使われ、ある小さなプログラムから別の小さなプログラムを呼び出すということを繰り返して、最終的にオペレーティングシステムが起動される。
初期のプログラム可能なコンピュータは、トグルスイッチがフロントパネルに並んでいて、それを操作することによってブートローダをプログラム格納域に置いてからCPUを起動するようになっていた。そうするとCPUはブートローダを実行して、オペレーティングシステムを外部記憶メディア(例えば紙テープあるいは磁気ディスク装置)からロードすることができた。例えば、IBM 650、DEC PDP-5、PDP-8、初期のPDP-11、Altair 8800 などの初期のマイクロコンピュータなどがスイッチを使っていた。フロントパネルのスイッチ群は直接CPUに命令列を渡すのにも使われた。例えば、PDP-1 はハードウェアにローダーを組み込んでいて、オペレータが "load" ボタンを押すだけで紙テープリーダからプログラムをメモリにロードすることができる。この紙テープリーダにはブートローダーが格納されており、それを実行すると二次ブートローダーまたはオペレーティングシステムを外部ストレージ媒体(紙テープ、パンチカード、ディスク装置など)からロードする。
ブートローダの擬似コードは以下の8個の命令に単純化できる。
P レジスタに 9 をセット
もし準備できていなかったら、2 へジャンプ
紙テープ読取装置からアキュムレータに 1バイト読み込む
テープが終了したら 9 へジャンプ
アキュムレータの内容を P レジスタが指すアドレスに書き込む
P レジスタに 1 を加算
2 へジャンプ
次の例は 1970年代のニコレット・インストゥルメント社のミニコンピュータに基づいている。二次ローダが紙テープから逆の順番に読み込まれることに注意。
P レジスタに 106 をセットする
もし準備できていなかったら、2 へジャンプ
紙テープ読取装置からアキュムレータに 1バイト読み込む
アキュムレータの内容を P レジスタが指すアドレスに書き込む
P レジスタから 1 を減算
2 へジャンプ
二次ローダの長さは、ちょうど最後に 7 番地を上書きする長さになっている。6 番地の命令を実行した後、7 番地から二次ローダを実行し始める。二次ローダはオペレーティングシステムが書いてあるもっと長いテープが紙テープ読取装置にセットされるのを待つ。ブートローダと二次ローダの違いは紙テープ読取装置がエラーを発生したときに対処できるかどうかである。当時のハードウェア(例えばASR-33)では紙テープ読取装置は頻繁にエラーを起こした。
一部システムは人間のオペレータか周辺機器からのブート信号を受けて、固定の小さな命令列をロードしてメモリ上の特定のアドレスに配置し、1つのCPUを初期化してその位置から実行を開始させる。その命令列は一般に何らかの周辺機器(オペレータがスイッチ操作で機器を指定する場合もある)からの入力操作を開始するものである。他のシステムは、周辺機器またはチャネル・コントローラに直接ハードウェアコマンド列を送り、単純な入力操作(例えば、システムデバイスの0番セクタをリードし、メモリの1000番地にリード結果を置く)を実施させ、小さなブート用命令列をメモリ上にロードさせる。そしてI/O完了を知らせる信号を契機として、CPUにその命令列を実行させることになる。
マイコンと呼ばれた時代の初期のパーソナルコンピュータ、だいたい16ビット時代の初期の頃までのマシンでは、フロッピーディスクが標準の装備でなかったこともあり、最初からメモリ空間にROMとしてプログラムが展開されて存在し、ほとんどにおいてはBASIC(ROM BASIC)を起動するというものがもっぱらで、外部記憶装置からシステムを読み込むブートシーケンスは存在しなかった。クリーンコンピュータを標榜したシャープの一部のパソコンのように例外もある。
最近のコンピュータではブート処理はCPUがROM内のソフトウェア(例えば、BIOSやEFI)を既定のアドレスから実行することで開始される(CPUはリセットされると外部からの助け無しにこのソフトウェア実行をするよう設計されている)。そのソフトウェアはブートに使用できる各種デバイスを探し、最も優先順位の高いデバイスの特殊な領域(一般にはブートセクタ)から小さなプログラムを読み込む。
ブートローダには特有の制限、特にそのサイズの制限がある。例えば IBM PC や互換機では、一次ブートローダは必ず446バイト(Windows NT では、ディスクシグニチャがオフセット440の位置にあるため、440バイト)でマスターブートレコードになければならず、その後に64バイトのパーティションテーブルが続き、最後が 0xAA55 という値で終わっていなければならない(BIOS はその値を見て正しいブートローダであると判断する)。
1995年以前の Macintosh などでは、OS とハードウェアが非常に密接に関連しており、標準のOS以外でブートすることができない。そのような場合、一般にとられる解決策としては、標準OSに属するプログラムとしてブートローダを設計し、それがシステムをハイジャックして別のOSをロードする。これは例えばアップルがA/UXというUnix系のOSのブートに使った技法で、それを流用して各種フリーウェアのOSや BeOS Personal Edition 5 などがブート可能となっていた。90年代によく使われていたMS-DOS環境からLinuxを起動するloadlin(w:Loadlin)も同様のものである(もっともMS-DOSには保護がないので、ハイジャックというほど大袈裟なものでもない)。
一般的な一次ブートローダーとしては、以下のものがある。
ブートローダが読み込む小さなプログラムは、オペレーティングシステムではなく二次ブートローダであることが多い。BOOTMGR、NTLDR、SYSLINUX、GRUBなどがある。二次ブートローダは実際のオペレーティングシステム (OS) をロードすることができ、最後にOSを実行する。OSは初期化処理を行い、デバイスドライバをロードし、OSの通常の処理に必要とされる他のプログラムをロードする。
GNU GRUB、Windowsの BOOTMGR、Windows NT/2000/XP の NTLDR といったブートローダーは、マルチブート設定が可能である。この場合異なるOSを指定することもできるし、同じOSの異なるバージョンを指定することもできるし、単に異なるオプションを指定することもでき(例えば、セーフモードで起動するなど)、OSではなく独立して動作するプログラムを指定することもできる(メモリテスタ Memtest86、ゲームなど)。ブートローダーに別のブートローダーをロードさせることもできる。例えば、GRUBがBOOTMGRをロードすることも可能である。一般にデフォルト設定があり、ある時間内にユーザーが選択しなければデフォルト状態でブートを行う。
なお、Windows 9x系ではMS-DOSが二次ブートローダのような役割を果たしている。ただし、MS-DOSを単体で起動することもできる。
ブート処理はコンピュータがユーザとやりとりできるようになった時点で完了したと見なされる。あるいは、オペレーティングシステムが普通のアプリケーションを実行できるようになった時点で完了と見なすこともできる。典型的なPCのブートは約 1 分ほどかかる。そのうち、15秒ほどが Power On Self Test (POST) が費やす時間で、残りはオペレーティングシステムのロードにかかる時間である。OSロード後の経過時間はシステム内のコアを同時に起動することで3秒程度にまで短縮可能で、例えばcorebootでそのようなブートが可能である。一方、大きなサーバでのブートは全てのサービス起動まで何分かかかる。
多くの組み込みシステムではほとんど即座にブートが完了しなければならない。たとえば、テレビが映るまでに1分かかったのでは使い物にならない。そのため、オペレーティングシステム全体を ROM やフラッシュメモリに格納して、直接実行できるようにしている。ただし、ROMやフラッシュメモリはRAMに比べると、2007年現在の水準では1000倍と桁違いに遅い為、複合機など高機能な機器ではROMの内容をRAMに書き出して実行している。VxWorksなどではROM上の直接実行形式で用意されたブートストラップローダーがROM上の圧縮されたプログラム本体をRAMに展開して本体プログラムが起動するという実装がとられている。
組み込みシステムでは、製造工程や保守工程でプログラムを変更するためにフラッシュブートローダが必須である。フラッシュブートローダはフラッシュメモリ内にあり、リセット後に最初に実行されるアプリケーションである。フラッシュブートローダを出荷製品に入れておくと、アプリケーションの更新・修正、設定の変更が容易に行える。CAN ベースのフラッシュブートローダが一般的であり、診断プロトコルを使って通信・ダウンロードを行う。
多くのコンピュータはコンピュータネットワーク経由でブートを行う機能を持っている。この場合、二次ブートローダ はサーバのディスクに格納されており、それを TFTP のような単純なプロトコルでクライアントに転送する。内蔵ディスクを持たないシンクライアントは、ネットワークブートによって起動される。
実装としてはPreboot Execution Environment(PXE)などが存在する。
ブートデバイスとはオペレーティングシステムをロードする前に初期化しなければならないデバイス(周辺機器)のことである。これには一つの入力機器(キーボード)、ひとつの出力機器(ディスプレイ)、初期プログラムロード用機器(フロッピーディスクドライブ、ハードディスクドライブ、CD-ROM、USBメモリなど)がある。初期プログラムロード (IPL = Initial Program Load) 用機器とは、オペレーティングシステムを格納し、ブート処理でOSをロードするのに使われる機器であり、他にも単独動作するユーティリティ(例えば、memtest86+)やブートローダが格納されている。古いシステムではこれはフロッピーかハードディスクと限定されていた。
最近のPCのBIOSは様々なデバイスからのブートをサポートしており、ローカルのハードディスク(あるいはディスク上のパーティション)、光学ドライブ、USBデバイス(フラッシュドライブ、ハードディスクドライブ、光学ディスクドライブなど)、フラッシュメモリカード、ネットワークカード(PXEを使用)などがある。古いPCではフロッピーディスクドライブ、ZIPドライブ、LS-120ドライブなどに限定されていた。
一般にユーザーがBIOSでブート順を設定することができる。1番目をDVDドライブ、2番目をハードディスクと設定した場合、BIOSはまずDVDドライブからのブートを試みる。そしてDVDがセットされていないなどの理由でブートに失敗するとローカルなハードディスクからのブートを試みる。DVDにLinuxの Live CD を入れておけば、ハードディスクにLinuxをインストールしなくともLinuxを起動することができる。これがマルチブートの一例であり、ユーザーはPOST実行後にどちらのOSを起動するかを選択できる。この場合は、電源投入時に(あるいはリセット時に)CDを入れておくか否かで起動するOSを選択しているが、一般的にはキーボードを使ってBIOSブートメニューを表示させて選択する(一般に F11 または ESC を押下)。
電源投入直後、ないしリセットにより、x86は、まずBIOSの存在する 0xFFFF0 番地のメモリにある命令を実行する(ここはx86を使用するどんなコンピュータでも同じである)。このメモリ位置は(リアルモードでの)システムメモリのほぼ最後尾にあたる。そこにはBIOSの初期プログラムの位置へのジャンプ命令が含まれていて、BIOSに制御が渡る。BIOS初期プログラムは Power On Self Test (POST) を実行して必要な機器が正常に動作するかをチェックする。また、同時にそれら周辺機器の初期化も行う。次にBIOSは事前に設定されたデバイスリストを順にあたって、ブート可能な周辺機器を探す。ブート可能デバイスとは、読み込みが可能で、第1セクタの最後尾に <tt>0xAA55</tt> というワード(ブートシグニチャ)があるデバイスである。
そのようなデバイスが見つからない場合、エラーが発生してブート処理は停止する。BIOSがブート可能デバイスを発見すると、そのブートセクタを 0x7C00 というアドレス(Segment:Offset形式では 0000:7C00 だが、一部のBIOSでは 07C0:0000 を使用)にロードして実行する。ハードディスクドライブの場合、ブートセクタはマスターブートレコード (MBR) と呼ばれ、その内容はオペレーティングシステムには依存しない。MBRのコードはパーティションテーブルを調べてアクティブなパーティションを探す。それが見つかったら、MBRのコードはパーティションのブートセクタをロードして実行する。ブートセクタはオペレーティングシステムに依存することが多いが、その機能はカーネルをロードして実行することである。カーネルはさらに初期化処理を続行する。アクティブなパーティションがなかったり、アクティブなパーティションのブートセクタが不正だった場合、MBRは第二ブートローダをロードして制御を渡す。第二ブートローダは(多くの場合ユーザーに入力してもらって)パーティションを選択して、そのブートセクタをロードする。パーティションのブートセクタは一般にオペレーティングシステムのカーネルをロードする。
一部システム(特に最近のMacintoshや Microsoft Windows)はインテルのEFIを採用している。EFI準拠のファームウェアを持つ比較的新しいシステムでは、MBR か GPT のあるドライブからブートでき、標準のMBRブートローダを使わない。また、corebootもシステムマネジメントモードを使った過剰に複雑なファームウェア/BIOSを使わずにブート可能である。古い16ビットBIOSインタフェースは一部のx86用OS(Windows 3.1/95/98など)で必要とされていただけだが、そういった古いBIOSシステムをサポートするためブートローダーは16ビットサポートを続けていることが多い。
BIOSとは異なり、UEFI(CSM経由のレガシー ブートではない)はブートセクタに依存せず、UEFIはブートローダー(USBフラッシュドライブまたはEFIシステムパーティション内のEFIファイル)を直接読み込み、OSカーネルはブートローダーによってロードされる。
多くのPCはBIOSチップを搭載していれば、BIOSチップメーカー名、著作権、そのチップのIDなどを起動時に表示する。同時に利用可能なメモリ容量など、そのコンピュータに関する情報も表示する。
他のプロセッサは異なるブートモードを持つ。
CPUやマイクロコントローラのブート方法として以下のような技法がある。
TI OMAP や一部のDSPは、ブートROMを内蔵しており、単独で洗練されたブートシーケンスを実行でき、NANDフラッシュ、SD、MMCカードなど各種ソースからブートプログラムをロードできる。各種デバイスへの対応を回路で実現するのは困難であり、その代わりにブートROMを集積している。ブートROMであれば、複数のデバイスからのブートを試行することもできる。また、UART、SPI、USBなどから診断プログラムやブートローダをロードすることもできる。不揮発性メモリ上のブートソフトウェアが何らかの原因で消去されてしまった場合なども、この機能を使って復旧することができ、製造直後に不揮発性メモリにプログラムを格納するのにも使える。
JTAGなどのハードウェアデバッグ用インタフェースを使ってシステムの制御を獲得することもできる。そのようなインタフェースを使ってブートローダーを不揮発性メモリ(フラッシュなど)に書き込むことができる。また、デバッグ用インタフェースを使ってRAMに診断コードやブートコードをアップロードすることもでき、アップロードしたコードをプロセッサに実行させることができる。ブートROMを集積していないプロセッサで、不揮発性メモリの内容が消去された場合、これを使って復旧を図る。
一部のマイクロコントローラはブート可能な不揮発性メモリにブートコードを書き込むことができる単純なプロトコルのインタフェースを用意している。製造時にそのようなインタフェースを使ってブートコードを不揮発性メモリに書き込む。システムをリセットすると、マイクロコントローラが自動的に不揮発性メモリ上のプログラムを実行開始する。例えば Atmel AVR などがこの方式である。この際のインタフェースはハードウェアで実装されていることが多い。ブートROMを持つプロセッサの場合、ブートROM上のソフトウェアでGPIOピンをそのようなインタフェースに使うこともできる。
多くのデジタルシグナルプロセッサ (DSP) には以下のようなブートモードがある。
パラレルモードブート(HPIブートなど)