d.sunnyone.org
sunnyone.org

ページ

2015-11-24

Linuxを使ってUEFIシステムのWindowsをセーフモードで起動させる

しばらくセーフモードのお世話になっていないうちに、セーフモードはF8で起動するものではなくなっていたらしい。セーフモードを構成してからシャットダウンしてセーフモードとか。回復ディスクがなく、Windowsが起動しない場合で、明示的にセーフモードで起動したいときはどうしたらいいんだろう?ということで、Linuxを使ってセーフモードを明示的に構成する方法について今回はまとめた。

注意:PCメーカーやMicrosoftの推奨する方法ではありません。壊れにくいような手順は取っていますが、重要なシステムに適用することはおすすめしません。普通に回復ディスクを使うのが楽だと思います。どちらかというと、仕組みを読み取ってもらえれば幸いです。

手順の概要

最近のWindowsの起動時の設定はBoot Configuration Data (BCD) というところに格納されており、ここにセーフモードで起動するかどうかの設定も入っている。そこで、このBCDをUSBメモリからブートしたUbuntuを使って書き換えることで、Windowsをセーフモードで起動させる。

なおBCD書き換えの際、標準外のツールを使うため、ファイルが壊される可能性を考慮して、セカンダリBCDストアを構成し、そちらの設定を変更することにする。

図にすると以下の通り。

環境/必要なもの

対象の環境は、UEFIで稼動するWindows。Windows 10で検証したが、Vista以降ならいけると思う。

また、必要なものはUbuntu 14.04 (or later) のブータブルUSBメモリ や DVD。すでにデュアルブート環境なら、それでも問題ない。

一応、検証した環境(VirtualBox)でのbcdeditコマンドの出力結果はこんな感じ。
Windows ブート マネージャー
--------------------------------
identifier              {bootmgr}
device                  partition=\Device\HarddiskVolume2
path                    \EFI\Microsoft\Boot\bootmgfw.efi
description             Windows Boot Manager
locale                  ja-JP
inherit                 {globalsettings}
default                 {current}
resumeobject            {43ea4f06-91dc-11e5-8faa-ac88953b08c0}
displayorder            {current}
toolsdisplayorder       {memdiag}
timeout                 30

Windows ブート ローダー
--------------------------------
identifier              {current}
device                  partition=C:
path                    \Windows\system32\winload.efi
description             Windows 10
locale                  ja-JP
inherit                 {bootloadersettings}
recoverysequence        {43ea4f08-91dc-11e5-8faa-ac88953b08c0}
recoveryenabled         Yes
isolatedcontext         Yes
allowedinmemorysettings 0x15000075
osdevice                partition=C:
systemroot              \Windows
resumeobject            {43ea4f06-91dc-11e5-8faa-ac88953b08c0}
nx                      OptIn
bootmenupolicy          Standard

手順

1) セカンダリブートパス・セカンダリBCDストアの構成

1-1) Ubuntuの起動

ブータブルUSBメモリなどでUbuntuを起動する。

1-2) EFI システムパーティション (ESP) のマウント

Ubuntuが起動したら、EFI システムパーティションをどこか適当な場所にマウントする。マウントしたら、EFI/Microsoft/Boot/BCDが存在することを確認しておく。
$ sudo parted /dev/sda print
モデル: ATA VBOX HARDDISK (scsi)
ディスク /dev/sda: 34.4GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt

番号  開始    終了    サイズ  ファイルシステム  名前                          フラグ
 1    1049kB  473MB   472MB   ntfs              Basic data partition          hidden, diag
 2    473MB   578MB   105MB   fat32             EFI system partition          boot
 3    578MB   595MB   16.8MB                    Microsoft reserved partition  msftres
 4    595MB   34.4GB  33.8GB  ntfs              Basic data partition          msftdata

$ sudo mkdir /mnt/efi
$ sudo mount /dev/sda2 /mnt/efi
$ find /mnt/efi -name BCD
/mnt/efi/EFI/Microsoft/Boot/BCD     ←Microsoft/Boot/BCDが存在することを確認
/mnt/efi/EFI/Microsoft/Recovery/BCD

1-3) Microsoftディレクトリのコピー

EFIアプリケーションであるWindows Boot Manager (bootmgfw.efi)及びその設定であるBoot Configuration Data (BCD)が含まれるMicrosoftディレクトリをコピーする。
$ cd /mnt/efi/EFI
$ sudo cp -pr Microsoft MicrosoftSafeMode

手順参考:Windows RE を起動するためのハードウェア回復ボタンの追加

2) セカンダリBCDストアのBCDの書き換え

2-1) hivexregeditツールのインストール

設定が格納されているBCDは、レジストリハイブの形式をとっている。そこで、レジストリハイブを編集できる「hivexregedit」ツールを使えるようにする。

「hivexregedit」ツールは、libwin-hivex-perlパッケージに入っているので、これをインストールすればOK。
$ sudo apt-get install libwin-hivex-perl
なお、他にもレジストリハイブを扱うツールがlibhivex-binパッケージにいくつか入っているので、必要があれば入れる。

2-2) BCDファイルをレジストリエディタ形式にエクスポート

hivexregeditの--exportオプションを使って、BCDの内容を*.regファイルでおなじみの形式にエクスポートする。
$ hivexregedit --unsafe-printable-strings --export /mnt/efi/EFI/MicrosoftSafeMode/Boot/BCD '\' > /tmp/bcd.reg
これにより、テキストエディタやビューワで表示が可能になった。--unsafe-printable-stringsをつけないと、文字列が軒並みhex表記になって見れたもんじゃない。

2-3) Windows Boot Managerのobjectを探す

@junichia氏のブログエントリ「ブート構成データ(BCD)ストアを理解すれば VHDブート は簡単」に図があるので見て欲しいのだけど、BCDにはひとつのWindows Boot Managerのobjectと、複数のWindows Boot Loaderのobjectがある。Boot Loader側にsafe modeの設定もあるのだけど、まずはどれがdefaultで利用されているBoot Loaderか確認するため、Boot Manager側のobjectを探し出す。

boot managerのオブジェクトを探し出すには「bootmgfw.efi」を文字列検索するのが簡単。
$ less /tmp/bcd.reg
(/で検索)
[\Objects\{9dea862c-5cdd-4e70-acc1-f32b344d4795}\Elements\12000002]
"Element"=str(1):"\EFI\Microsoft\Boot\bootmgfw.efi^@"

[\Objects\{9dea862c-5cdd-4e70-acc1-f32b344d4795}\Elements\12000004]
"Element"=str(1):"Windows Boot Manager"

これで、boot managerのオブジェクトのGUIDが「{9dea862c-5cdd-4e70-acc1-f32b344d4795}」であることがわかった。

なお、各項目はElements\以下の数値で何か判断することが可能である。上記における「12000002」は「BcdLibraryString_ApplicationPath」でbcdeditコマンドでは「path」として表示される。同様に「12000004」は「BcdLibraryString_Description」でbceditコマンドでは「description」である。それぞれの数値が何を意味するかは、MSDNにも記述があるのだが、Geoff Chappell氏の「BCD Elements」が見やすくておすすめである。

2-4) Widnows Boot Managerのobjectから「default」を探し出す

Boot Managerがわかったので、そのGUIDを利用して、デフォルトのBoot Loaderの指定を探し出す。デフォルトのBoot Loaderが記述されているのはBcdBootMgrObject_DefaultObject (default)で「23000003」である。

$ less /tmp/bcd.reg
(/で検索)
[\Objects\{9dea862c-5cdd-4e70-acc1-f32b344d4795}\Elements\23000003]
"Element"=str(1):"{43ea4f07-91dc-11e5-8faa-ac88953b08c0}"

ここでデフォルトのBoot Loaderが{43ea4f07-91dc-11e5-8faa-ac88953b08c0}であることがわかった。一応、{43ea4f07-91dc-11e5-8faa-ac88953b08c0} のBcdLibraryString_ApplicationPath (path) 「12000002」及び BcdLibraryString_Description (description) 「12000004」を確認しておく。
$ less /tmp/bcd.reg
(/で検索)
[\Objects\{43ea4f07-91dc-11e5-8faa-ac88953b08c0}\Elements\12000002]
"Element"=str(1):"\Windows\system32\winload.efi"

[\Objects\{43ea4f07-91dc-11e5-8faa-ac88953b08c0}\Elements\12000004]
"Element"=str(1):"Windows 10"
これでいいようだ。

2-5) Boot Loader objectにセーフモード設定を組み込む

Boot Loaderのobjectにセーフモード関連のElementを追加する*.regファイルを作り、それをhivexregeditの--mergeオプションを使って組み込む。

項目がいくつかあるので後の表を見て欲しいが、例えばmsconfigで言うところのセーフモード: 代替シェルで起動する記述は以下の通りである。生成したbcd.regをコピーして作るのが楽。
$ cp /tmp/bcd.reg /tmp/bcd-safe.reg
$ vi /tmp/bcd-safe.reg
~~~
Windows Registry Editor Version 5.00

[\Objects\{43ea4f07-91dc-11e5-8faa-ac88953b08c0}\Elements\25000080]
"Element"=hex(3):00,00,00,00,00,00,00,00

[\Objects\{43ea4f07-91dc-11e5-8faa-ac88953b08c0}\Elements\26000081]
"Element"=hex(3):01
~~~
上記の例ではBcdOSLoaderInteger_SafeBoot (safeboot) 「25000080」を「Minimal」にし、BcdOSLoaderBoolean_SafeBootAlternateShell (やsafebootalternateshell) 「26000081」をtrueにしている。

以下は検証したわけではないが、msconfig.exeの「ブート」タブの表示(以下参考)とbcdeditの出力を見ながら、「BCD Elements」とつきあわせて表にまとめたものが以下となる。


msconfigの項目bcdeditの項目名称Element備考
pathBcdLibraryString_ApplicationPath 12000002string
descriptionBcdLibraryString_Description 12000004string
defaultBcdBootMgrObject_DefaultObject23000003GUID
セーフブートsafebootBcdOSLoaderInteger_SafeBoot 250000800: 最小(Minimal) /
1: ネットワーク(Network) /
2: Active Directory修復(DsRepair)
(代替シェルのときのみ)safebootalternateshellBcdOSLoaderBoolean_SafeBootAlternateShell26000081boolean
GUI ブートなしquietbootBcdOSLoaderBoolean_DisableBootDisplay26000041boolean
ブートログbootlogBcdOSLoaderBoolean_BootLogInitialization 26000090boolean
基本ビデオvgaBcdOSLoaderBoolean_UseVgaDriver26000040boolean
OS ブート情報sosBcdOSLoaderBoolean_VerboseObjectLoadMode26000091boolean

regファイルを作ったら、--mergeでmergeする。
$ sudo hivexregedit --merge /mnt/efi/EFI/MicrosoftSafeMode/Boot/BCD /tmp/bcd-safe.reg

再度hivexregedit --exportしてみて、組み込まれていればOK。

2-6) umount

言うまでもないかもしれないが、umountしておく。
$ sudo umount /mnt/efi

3) grubから新しいBCDを使って起動

UbuntuをEFIで起動しているということは、EFIで動作するgrubが使えるということである。そこで、そのgrubを利用して上記で作ったセカンダリブートパス・BCDストアを選択して起動する。

再びUbuntu ブータブルUSBメモリで再起動し、grubメニューが現れたら、「c」キーを押しコンソールモードに切り替える。切り替わったら、以下のように入力して、新しいbootmgfw.efiを使って起動する。

grub> set root=(hd0,gpt2)
grub> chainloader /efi/MicrosoftSafeMode/Boot/bootmgfw.efi
grub> boot

hdのパスはPCによって異なるはずなので、以下の図のようにTAB補完を活用しながら入力するとよい。


これでセーフモードで立ち上がってくれば成功。とくにEFI firmware側の設定は変更していないので、ブータブルUSBメモリを外して普通に起動すれば元通り。気になるようであれば、EFIシステムパーティションから今回作ったディレクトリを削除しておけばOKである。


0 件のコメント:

コメントを投稿