MacBookが起動するまで何が起こっているのか?

すべてはMacBookの電源ボタンを押した瞬間に、始まる。フラッシュ ストレージ搭載のAirにおいては、その僅か15秒後には起動が完了して、美しいGUIがユーザーの操作を待ち構える。その15秒間に一体何が起こっているのか?
前回は、プロセスID 0 まで遡ってみた。しかし、それより前の世界がまだ全然見えていない。今回は、電源オンから時系列に辿ってみようと思う。

概要・基礎知識

CPUの本能
  • CPUは複雑怪奇なスイッチの集合体だけど、できることは非常にシンプル。メモリの内容を読み込んで、読み込んだ命令に従って演算して、結果をまたメモリへ出力するだけ。
  • つまり、メモリにプログラムとして実行可能な意味のある数列が展開されていないと、CPUは無意味な動作を永遠と続けるだけなのだ。
  • だから、電源オンでCPUが稼働した瞬間から、何らかの意味のあるプログラムが用意されていて、それが忠実に実行され、美しいGUIを操作できる環境まで至っているはず。
電源オン直後の世界
  • ところで、コンピュータはプログラムが無ければ、役立たずの箱と言われている。そして、電源オンした瞬間は、まさしくその役立たずの箱状態なのだ。
  • RAMメモリやレジスタの値は、0であるかどうかさえ保証されていない。ハードディスクにアクセスするドライバもなく、ディスプレイに出力する手段もない。
  • そんな無の状態から、何を手がかりに始まって行くのか?
保証された値

追跡するための作戦

  • 15秒で起動してしまうMacBookAirと違って、自分の白MacBookは余裕で1分以上、一生懸命に起動処理をしている。
  • 普段は再起動に時間がかかってイライラするけど、じっくり観察したいこんな時には、のんびりしたMacBookもまた良い。
  • しかし、ただ眺めているだけでは得られるものは少ない。
  • OSが起動するまでのステップごとに、なるべく立ち止まれるような方法で起動してみる。
  • そして、普段は表示されないが、起動中のメッセージも画面に出力するようにしておく。

その手順は以下のようにしてみた。

  • システム環境設定 >> アカウント >> ログインオプションで、自動ログインは「切」にしておく。
  • (1)optionキーを押しながら、電源オン。
  • (2)Startup Manager(スタートアップ マネージャー)が表示される。
  • (3)Startup Managerで、起動ディスクを選択する。
  • (4)「command + S」キーを押しながら、returnキーを押して実行する。
  • (5)シングルユーザーモードで起動が始まり、起動中のメッセージが画面に出力される。
  • (6)コマンド待ちの状態になる。
  • (7)exitコマンドでシングルユーザーモードを抜け出し、通常の起動処理が始まる。
  • (8)ログインウィンドウが表示される。
  • (9)ログインする。

出力されたメッセージ(OSX10.6.8のみインストールした環境において)

  • (1)optionキーを押しながら、電源オン。
  • (2)Startup Manager(スタートアップ マネージャー)が表示される。

  • (3)Startup Managerで、起動ディスクを選択する。
  • (4)「command + S」キーを押しながら、returnキーを押して実行する。
  • (5)シングルユーザーモードで起動が始まり、起動中のメッセージが画面に出力される。
efiboot loaded from device: Acpi(PNP0A03,0)/Pci(1A10)/Usb(1, 0)/HD(Part4,Sig5A02D2E4-05B8-4072-07BAF8ACC685)
boot file path: \System\Library\CoreServices\boot.efi
.Loading ’mach_kernel’...
.....................
root device uuid is ’22EB6B8B-1310-8ACD-A90A-A7A682A6094D’
Loading drivers...
Loading System\Library\Caches\com.apple.kext.caches\Startup\Extensions.mkext...
.....
    • カーネルの起動が始まる。
    • 以下のメッセージは、コンソール.app の kernel.log でも確認できる。
npvhash=4095
PAE enabled
64 bit mode enabled
Darwin Kernel version 10.5.0: Fri Nov  5 23:20:39 PDT 2010; root:xnu-1504.9.17~1/RELEASE_I386
vm_page_bootstrap: 1533522 free pages and 31150 wired pages
standard timeslicing quantum is 10000 us
mig_table_max_displ = 73
AppleACPICPU: ProcessorID=0 LocalApicID=0 Enabled
AppleACPICPU: ProcessorID=1 LocalApicID=1 Enabled
calling mpo_policy_init for Quarantine
Security policy loaded: Quarantine policy (Quarantine)
calling mpo_policy_init for Sandbox
Security policy loaded: Seatbelt sandbox policy (Sandbox)
calling mpo_policy_init for TMSafetyNet
Security policy loaded: Safety net for Time Machine (TMSafetyNet)
Copyright (c) 1982, 1986, 1989, 1991, 1993
        The Regents of the University of Callifornia. All rights reserved.

MAC Framework successfully initialized
using 16384 buffer headers and 4896 cluster IO buffer headers
IOAPIC: Version 0x20 Vectors 64:87
ACPI: System State [S0 S3 S4 S5] (S3)
AppleIntelCPUPowerManagement: initialization complete 
mbinit: done (64 MB memory set for mbuf pool)
rooting via boot_uuid from /chosen: 22EB6B8B-1318-3ACD-A98A-A7A632A6894D
Waiting on <dict ID=“8”><key>IOProviderClass</key><string ID=“1”>IOResources</string><key>IOResourceMatch</key><string ID=“2”>boot-uuid-media</string></dict>
com.apple.AppleFSCompressionTypeZlib kmod start
com.apple.AppleFSCompressionTypeZlib load succeeded
AppleIntelCPUPowerManagementClient: ready
FireWire (OHCI) Lucent ID 5811 built-in now active, GUID 082332fffe8e1e7c; max speed s400.
USBMSC Identifier (non-unique): 888888888888 0x152d 0x2336 0x100
[Bluetooth::CSRHIDTransition] Single User - waiting WindowServer
Got boot device = IOService:/AppleACPIPlatformExpert/PCI0/AppleACPIPCI/EHC2@1A,7/AppleUSBEHCI/JM20336 SATA, USB Combo@fa200000/Bulk-In, Bulk-Out Interface@0/IOUSBMassStorageClass/IOSCSIPeripheralDeviceNub/IOSCSIPeripheralDeviceType00/IOBlockSto
BSD root: disk1s4, major 14, minor 7
com.apple.launchd 1     com.apple,launchd 1     *** launchd[1] has started up. ***
Singleuser boot ―- fsck not done
Root device is mounted read-only

If you want to make modifications to files:
        /sbin/fsck -fy
        /sbin/mount -uw /

If you wish to boot the system:
        exit

:/ root#
  • (6)コマンド待ちの状態になる。
    • いくつかコマンドを実行して、現在の状態を調べみた。
/ root#
bold;">launchctl list
PID Status Label 6 - 0x100300648.anonymous.launchctl 3 - 0x101800000.anonymous.sh 2 - com.apple.launchctl.System
/ root#
bold;">ps -axj
USER PID PPID PGID SESS JOBC STAT TT TIME COMMAND root 1 0 1 a92ee78 0 Rs ?? 0:00.04 /sbin/launchd -s root 2 1 1 a92ed40 0 Ss ?? 0:00.06 /sbin/launchctl bootstrap -S System -s root 3 2 1 a92ec08 0 Ss ?? 0:00.05 -sh root 7 3 1 a92ee08 1 R+ ?? 0:00.00 ps -axj
/ root#
bold;">kextstat | grep -v com.apple
Index Refs Address Size Wired Name (Version)
    • シングルユーザーモードでは...
    • kernel_task[0]とlaunchd[1]は、起動している状態。([0] = プロセスID 0 の意味)
    • launchctl bootstrapは、おそらく起動時に自動ロードされるLaunchAgents・LaunchDaemonsを起動するプロセス。スリープしている状態。
    • そして、現在のコマンド環境を提供するsh(シェル)が、ps -axjコマンドを実行してい状態。
    • カーネル機能拡張は、OSXデフォルトのものしかロードされていない状態。
  • (7)exitコマンドでシングルユーザーモードを抜け出し、通常の起動処理が始まる。
    • 以下のメッセージは、コンソール.app の kernel.log でも確認できる。
/ root#
bold;">exit
logout systemShutdown fales Waiting for DSMOS... Previous Shutdown Cause: 5 BTCOEXIST off wl0: Broadcom BCM4328 802.11 Wireless Controller 5.10.181.86 DSMOS has arrived [Bluetooth::CSRHIDTransition] switchToHCIMode (legacy) IntelMemory::init IntelMemory::init InitPool: offset= 0x08000000 size = 0x08000000 AirPort_Brcm43224: Ethernet address 00:28:12:08:ff:99 IO80211Controller::dataLinkLayerAttachComplete(): adding AppleEFINVRAM notification AirPort: Link Down on en1. Reason 1 (Unspecified). [Bluetooth::CSRHIDTransition] transition complete. Waiting for window server before finishing buletooth setup Auth result for: 00:1f:5b:39:87:ed MAC AUTH succeeded AirPort: Link Up on en1 AirPort: RSN handshake complete on en1
  • (8)ログインウィンドウが表示される。
  • (9)ログインする。
    • ログインする時には、以下の項目が起動される。
    • LaunchAgents で指定された項目。
    • ログイン項目。

時系列に追跡する

以上の起動時のメッセージと、いくつかの文献を参考に、自分が理解した手順を時系列に並べてみる。

現在のOSXでは launchd が活躍しているが、以下のページの解説は非常に面白い!とっても参考になる。(感謝です!)

電源オン
電源LED点灯
ブラック画面
  • POST = Boot-ROM/RAM 等のチェックを開始
    • 電源投入時の自己診断テストを POST (Power-On Self Test) と呼ぶ。
    • 幾つかのハードウェアの初期化や確認,メモリのテスト等を行うらしい。
    • 再起動した場合は実行されない。
RAM エラーの場合
  • ブラック画面のまま、電源LEDが1秒間に1回の点滅を繰り返している = RAM が物理的に損傷している、間違った種類の RAM が取り付けられている、または RAM が取り付けられていない。
  • グレー画面になって、警告が3回鳴り、電源LEDが3回点滅を繰り返している = RAM がオペレーティングシステムに対応していない。
  • 上記エラーは、メモリの取り付け直しで解決する可能性あり。
起動音(ジャーン)
  • 電源投入自己診断テストが正常終了した合図。
  • と同時に、これからEFIブートが始まる合図。
Startup Managerが起動(optionキーを押している場合)
  • この時点ではまだ、起動ディスクをリストアップするだけ。
  • ハードディスク内の起動プログラムの読み込みは、行われていない。

グレー画面
アップルロゴの表示
  • boot.efi ファイルのロード。(/System/Library/CoreServices/boot.efi
ネットワークブートの場合
  • 点滅する球体が表示されている場合 ― ネットワークブート用サーバでのブーター/カーネルの検索中。
  • 回転する地球儀の下にメタリックなアップルのロゴが表示されている場合 ― ネットワークブート用サーバのブーター/カーネルのロード。
boot.efi ファイルのロード エラーの場合
  • 斜線のついた円(通行止めマーク)が表示されている場合 ― boot.efi ファイルがロードできない、またはその他の問題。
  • 点滅する壊れたフォルダが表示されている場合 ― ブート可能なデバイスが見つからない。
アップルロゴの下でイージケーターが回転
  • カーネルのロード。
    • 可能であれば、System\Library\Caches\com.apple.kext.caches\Startup\Extensions.mkext にアーカイブされたカーネルがロードされる。(起動時間の短縮のため)
ブルー画面
  • launchdの起動。
    • LaunchDaemons で指定された項目が起動される。
ログインウィンドウ
  • ログイン ボタンを押すと、ログインウィンドウに「ログイン中」というテキストと進行状況バーが表示される。(数秒)
  • ログインする時には、以下の項目が起動される。
    • LaunchAgents で指定された項目。
    • ログイン項目。
  • ログインに成功すると、デスクトップと Dock が表示される。
ログイン項目を起動させない場合
  • shiftキーを押しながら、ログイン ボタンをクリックする。

POSTとは?

  • POSTエラーを体験してみたい場合は、RAMメモリを抜いてMacBookを起動してみる。
    • ビープ音が1回鳴って、電源LEDが1回点滅、それを5秒間隔で繰り返した。

EFIとは?

EFIはどこにある?
  • EFIは、ROMあるいはフラッシュメモリ上に保存されている。
    • 電源オン直後のOSもドライバも存在しない環境で、CPUが直接認識できるメモリ上に展開されている必要があるのだ。
EFIパーティション
  • また、普段は見えないが、diskutilコマンドを使うとEFIパーティションの存在が確認できる。
$ diskutil list
/dev/disk0
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *500.1 GB   disk0
   1:                        EFI                         209.7 MB   disk0s1
   2:                  Apple_HFS Leopard HD              499.8 GB   disk0s2
NVRAM
  • NVRAM(電源オフでも値が保持されるRAM)にも、EFIブートのための情報が保存されていた。
$ nvram -p
boot-args	arch=i386
IORegistryCurrentSleepMode	true%00
SmcFlasherResult	%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00
prev-lang:kbd	ja:0
platform-uuid	%00%00%00%00%00%00%10%00%80%00%00#2%97%92%1a
boot-image	%02%01%0c%00%d0A%03%0a%00%00%00%00%01%01%06%00%00%1a%03%05%06%00%01%00%04%04%18%005%001%00c%005%001%00b%000%000%000%00%00%00%7f%ff%04%00
efi-boot-device	<array><dict><key>IOMatch</key><dict><key>IOProviderClass</key><string>IOMedia</string><key>IOPropertyMatch</key><dict><key>UUID</key><string>C9A8AD8A-E4EB-4EDA-B0FE-DCB17DD0E2A3</string></dict></dict><key>BLLastBSDName</key><string>disk0s2</string></dict></array>%00
fmm-computer-name	zari-MacBook
efi-apple-payload0	<array><dict><key>IOMatch</key><dict><key>IOProviderClass</key><string>IOMedia</string><key>IOPropertyMatch</key><dict><key>UUID</key><string>0B00F75C-090C-47AE-B7B4-F356F91E246B</string></dict></dict><key>BLLastBSDName</key><string>disk0s1</string></dict><dict><key>IOEFIDevicePathType</key><string>MediaFilePath</string><key>Path</key><string>\EFI\APPLE\FIRMWARE\k36a.smc</string></dict></array>%00
efi-apple-payload0-data	%02%01%0c%00%d0A%03%0a%00%00%00%00%01%01%06%00%02%1f%03%12%0a%00%00%00%00%00%00%00%04%01*%00%01%00%00%00(%00%00%00%00%00%00%00%00@%06%00%00%00%00%00\%f7%00%0b%0c%09%aeG%b7%b4%f8V%f9%1e$k%02%02%04%04>%00\%00E%00F%00I%00\%00A%00P%00P%00L%00E%00\%00F%00I%00R%00M%00W%00A%00R%00E%00\%00k%003%006%00a%00.%00s%00m%00c%00%00%00%7f%ff%04%00
efi-boot-device-data	%02%01%0c%00%d0A%03%0a%00%00%00%00%01%01%06%00%02%1f%03%12%0a%00%00%00%00%00%00%00%04%01*%00%02%00%00%00(@%06%00%00%00%00%00%e0%1f.:%00%00%00%00:%ad%a3%c9%eb%e4%daN%b0%fe%dc%b1}%d0%e2%a8%02%02%7f%ff%04%00
SystemAudioVolume	'

起動時のキーコンビネーション

起動時に「C」キーを押す。起動可能な CD または DVD から起動する。
起動時に「D」キーを押す。Apple Hardware Test で起動する。
起動時に「option + command + P + R」キーを押し続ける。
(ビープ音が 2 度鳴るまで)
NVRAM をリセットする。
起動時に「option」キーを押す。Startup Manager で、起動する Mac OS X ボリュームが選択できる。
起動時に「N」キーを押す。互換性のあるネットワークサーバ (NetBoot) から起動しようとする。
起動時に「opition + N」キーを押す。Startup Manager で、起動する Mac OS X ボリュームが選択できる。
(ネットワークボリュームも含む)
起動時に「T」キーを押す。FireWire ターゲットディスクモード で起動する。
起動時に「shift」キーを押す。セーフブートモードで起動し、ログイン項目を一時的に無効にする。
起動時に「command + V」キーを押す。Verbose モード(詳細な起動ログを出力するモード)で起動する。
起動時に「command + S」キーを押す。シングルユーザモード (Single-User mode) で起動する。
起動時に「イジェクト」キー、「F12」キー、マウスのボタン、
トラックパッドのボタン、いずれかを押し続ける。
光学式ディスクなどのリムーバブルメディアをすべて取り出す。

http://support.apple.com/kb/HT1533?viewlocale=ja_JP

起動までに実行されるステップまとめ

  • POST(電源投入自己診断プログラム)の実行
    • 電源オン
  • EFIファームウェアの実行
    • 「ジャーン」鳴る
    • Startup Managerによる起動ディスクの選択が可能
  • boot.efiの実行(/System/Library/CoreServices/boot.efi
    • Appleロゴが表示される
  • kernel_taskの起動処理(可能であれば /System/Library/Caches/com.apple.kext.caches/ を利用して起動時間の短縮を目指す)
    • Appleロゴの下で歯車イージケーターが回転する
  • launchdの起動
    • ブルー画面が見える
  • LaunchDaemonsを実行
    • ログインウィンドウが表示される
  • LaunchAgents・ログイン項目の実行
    • ログイン