ページ

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である。


2015-11-15

Loqui 0.6.3 リリース(クラッシュバグの修正)/Git移行

Loqui 0.6.3をリリースしました。一部環境でチャンネルツリーを(ダブル)クリックしたとき、segfaultして落ちることがあるようです。ここでは再現しないのですが、影響する環境では発生頻度は高そうなので、基本的にバージョンアップをおすすめします。
https://launchpad.net/loqui

Gitの特殊オペレーションに慣れすぎてBazzarがしんどくなってきたので、メインのブランチをGitに移行しました。レポジトリはLaunchpadのままです。基本 https://code.launchpad.net/loqui にある通りですが、sshを使う場合はlaunchpad login名をgit+ssh://hoge@ というふうにつけてあげる必要があるのでご注意ください。


---
落ちていた場所は、Gtk側からのツリーノードの件数の取得要求に答えるコードで、GtkTreeModelの規約にあっていなかった。呼ばれてなくても呼ばれていてもまぁそういうメソッドかな、数数えるならこっち呼んだほうがよくねって呼ぶようになったのかなという感じなんだけど、環境によって呼ばれたり呼ばれなかったりするのは謎。

2015-11-08

失われたUEFIブートエントリを取り戻す(Ubuntu インストールメディアから)

ある夕暮れ。VT-xを有効にすべくBIOS設定画面をいじっていて、再起動しようと思って「Reset」ボタンを押したら、再起動ボタンではなくFactory Resetボタンだった。設定が工場出荷時に戻されるのはまぁ戻せばいいのだけど、問題はブートエントリまで消されてしまったために、Ubuntuが起動できなくなってしまったということだ。

危険なResetボタン

update-grubすれば万事OKよね、と思っていたがそうでなかったので、UbuntuのUSBメモリを使って復旧する手順を記録しておく。

復旧手順

「Rescue a broken system」でレスキューモード起動

 Ubuntu 14.04 Server のUSBメモリをUEFIで起動すると、grubメニューが現れる。その中の「Rescue a broken system」を選んで起動する。

Serverなのは手元にあっただけで、Desktopなら普通のliveブートできるからもうちょっと楽かもね。

rootをインストール先にしてshell起動

言語だとかを選びウィザードを進めていくと、ルートファイルシステムを選ぶ画面が現れるので、Ubuntuをインストールしたパーティション、例えば/dev/sda6を選択後、「Execute a shell in /dev/sda6」を選んで、シェルを起動する。

efibootmgrでエントリが存在しないことを確認

efibootmgr あるいは efibootmgr -v(-vは詳細情報を表示)と叩くと、記録されたブートエントリの一覧が確認できる。

以下は例。長いID他が出ているが本筋ではないので省略した。
# efibootmgr -v
BootCurrent: 0015
Timeout: 0 seconds
BootOrder: 0000,0012,0013,0014
Boot0000* Windows Boot Manager HD(2,fa800,82000,(略))File(\EFI\Microsoft\Boot\bootmgfw.efi)WIND
OWS.........x...B.C.D.O.B.J.E.C.T.=.(略)
Boot0010  Setup FvFile((略))
Boot0011  Boot Menu FvFile((略))
Boot0012* Built-in Storage Device VenMsg((略))
Boot0013* USB Device VenMsg((略))
Boot0014* Network VenMsg((略))
Boot0015* Onetime Boot Device VenMsg((略))
Boot0016* VaioNextBoot Device VenMsg((略))
UbuntuやLinuxらしき項目は見つけられない。

/boot/efiにEFIパーティションをマウント

ブートローダが格納されているパーティションを/boot/efiにマウントする。今回は/dev/sda2なので以下の通り。
# mount /dev/sda2 /boot/efi
パーティションがどこなのかは、fdisk -lやparted /dev/sdX print、efibootmgr -vの出力、/etc/fstabの記述などから判断する。

grub-installによる復旧

grub-installでブートローダをインストールする。
# grub-install --bootloader-id ubuntu /dev/sda
もっとローレベルにefibootmgr -cでもできると思うが、試していない。

efibootmgrによる確認

efibootmgr -vを実行し、ubuntuの行があること、その行がBootOrderの先頭にあることを確認する。
# efibootmgr -v
BootCurrent: 0015
Timeout: 0 seconds
BootOrder: 0001,0000,0012,0013,0014
Boot0000* Windows Boot Manager HD(2,fa800,82000,(略))File(\EFI\Microsoft\Boot\bootmgfw.efi)WIND
OWS.........x...B.C.D.O.B.J.E.C.T.=.(略)
Boot0001* ubuntu HD(2,fa800,82000,(略))File(\EFI\ubuntu\shimx64.efi)
Boot0010  Setup FvFile((略))
Boot0011  Boot Menu FvFile((略))
Boot0012* Built-in Storage Device VenMsg((略))
Boot0013* USB Device VenMsg((略))
Boot0014* Network VenMsg((略))
Boot0015* Onetime Boot Device VenMsg((略))
Boot0016* VaioNextBoot Device VenMsg((略))

これで再起動して、Grubメニューが出てきたら成功。

参考:Restore Ubuntu UEFI Boot Entries after BIOS Update
---

このブートエントリ飛ばしちゃった問題は某co-edoで起きていたのだけど、うっかり復旧しようとしてたら確実にこれで時間を使いきっていた。あきらめて正解であった。

2015-11-03

図解 Amazon EC2 Container Service (ECS)

本当にざっと使ってみたので、説明用に絵にしてみた、という話。説明書きはつけたけど、図解と言うほどには、説明していないかも。



触った感じ、動き的にはこうじゃないかと思うのだけど、違っているところがあるかもしれない(のでRev0.1)。

並べるものではないのだけど、Beanstalkを使ったときは、Beanstalkが広く面倒を見るせいで、便利そうな反面意識するところが増えてかえってしんどいなと思ったのだけど、ECSは層の分割がしっかりしているおかげで、だいぶ扱いやすそうだなと思う。「Agent入りのインスタンスくれたら、そこのDockerコンテナを管理するよ。そこで何動かすかは知らないよ」という感じで、役割分担がはっきりしている。

Agent入れればdistributionはなんでもOKということだけど、こだわりがなければECS-Optimized Amazon Linuxを使っておいて、なるべくホスト側には手を入れないというのが、らしい使い方だろうか。

ECS-Optimized Amazon Linuxがあるとはいえ、VMが利用者管理なのはAWSらしいなと思う。もうちょっと基礎側がmanagedなやつがあればいいなぁと思うけど、そういった向きはAPI Gateway + Lambdaとかになるのかねえ。

MSI N3150I ECO と Ubuntu 14.04.3 の罠

以下の構成でPCを組んだ。用途によっては良い構成だと思うので、後々の参考のためメモ。

M/B(CPU)MSI N3150I ECO (Celeron N3150 Braswell)
メモリCrucial 4GB DDR3-1600 SO-DIMM 1.35V CL11 (CT51264BF160B)
HDDHGST 2.5" 500GB/5400rpm (0S03794)
ケースIN WIN IW-BM639余ってたやつ
ケースファンAinex OMEGA TYPHOON 8cm/15mm厚 (2000rpm/25.26cfm/20.4db)

第385回 Celeron N3150で省エネPC生活:Ubuntu Weekly Recipe」では、いくや先生が「IW-BP671/300B」で組んでいるのだけど、うちの「IN WIN IW-BM639」はそれのずっと昔のモデルだと思う。多分「Wavy II(IW-BMR651)」が現行モデルで、ちょっとずつデザインを変えながら生き続けている模様。このサイズで3.5"ドライブを2つ格納する場所がある上、ロープロファイルの拡張カードが挿せるのはオンリーワンだと思うのでIN WINには引き続き作って頂きたい。(拡張スロットが2つついていても、Micro-ATXが入るわけではないだろうし、Mini-ITXだとつけようがないと思うのだけど、一体何がささるのだろうというのはあるが。)

メモリは別の構成用に検討したので1.35Vになってるだけで1.5V使えるらしいし、HDDも3.5インチ入るのに2.5インチなのは単に静かそうだからってだけ。

しかし、ここまで到達するのに紆余曲折あったので、順番がおかしいのだけど、はまりそうな順に。

罠1: インストーラがインストールメディアを認識しない

Ubuntu 14.04 (14.04.3) をインストールしたのだけど、ちょっとだけコツがある。インストール中にCD-ROM(USBメモリ)の認識に失敗する(「cd-rom couldn't be mounted」というメッセージが表示される)ので、Alt+F2でコンソールに降りて以下のコマンドを叩いた後、インストーラ画面に戻ってボタンを押すとなぜか進む。Braswellのせい?USBメモリの作り方が悪い?

# df
→/mediaがマウントされている場所を確認。ここではsdb2とする。
# umount /media/
# mount /dev/sdb2 /cdrom

参考:debian - Unattended installation of Ubuntu from USB drive -- Not mounted correctly - Server Fault

罠2: ケースファンとメモリモジュールが当たる

写真の通り、メモリスロット1の位置とケースファンを設置する位置が近いので、もともとつけていたよくある25mm厚のファンだと干渉して配置することができなかったので、15mm厚のファンに取り替えた。ケースファンなんてなくてもいけそうな構成だけど一応つけてみた。スロット2があるからそっち使えば?と思うかもしれないが、1枚しか挿さない場合は1のほうに挿すことになっているらしいのだ。
写真はうまく入っている15mm厚のファンをつけた場合。マザーボードとケースの板までの間隔は20mm程だったので、それ以下でないとあやしい。

罠3: ASRock N3150-ITX には ATX12V がない(拡張カードを使うには電力不足)

最初は、Weekly RecipeにあわせてASRockで組んでいたのだけど、PCI-E x1スロットはあるものの、拡張カードによってはドライブできない(できなかった)のでやめた。N3150-ITXにはATX12V (「田」の形をしているコネクタ)がないので、PCI-Expressへの電力が足りないのだと思う。拡張カードを挿す予定ならこのMSI N3xxI ECOが良いと思う。

パフォーマンス

別に期待してないからどうでもいいのだけど、CPU性能はどんなもんかなと思ってうちの子達とsysbenchを使ってざっくり測ってみた。

「sysbench --test=cpu --cpu-max-prime=20000 --num-threads=$I」のtotal time。数値が小さいほど処理にかかった時間が短い。

CPU / --num-threads124
Atom CPU N270 @ 1.60GHz (2008, Diamondville, 1C/2T, 2.5W) 341.3614207.2697207.3816
Celeron N3150 @ 1.60GHz (2015, Braswell, 4C/4P, 6W) 52.550225.218112.5651
Core2 Duo P8600 @ 2.40GHz (2008, Penryn, 2C/2T, 25W)32.207717.155417.1533
Core i7-5500U CPU @ 2.40GHz (2015, Broadwell, 2C/4T, 15W)25.021812.93997.7414
Core i5-3570S CPU @ 3.10GHz (2012, Ivy Bridge, 4C/4T, 65W)22.27211.44816.2018
Core i7-4790S CPU @ 3.20GHz (2014, Haswell Refresh, 4C/8T, 65W)20.589310.54065.5582

整数演算だけ見てもなぁというところだけど、ざっくり。カテゴリ的には上の表でめちゃくちゃ遅いN270と似たような立ち位置になると思うのだけど、さすがに年代が進んでかなり速くなっているといえる。

ちなみに計測はこんな感じでやった。1回の結果しか使わない雑っぷり。


[2016/5/10 追記]
別の環境でも試してみた。
CPU / --num-threads124
Core i7-2700K @ 3.50GHz (2011, Sandy Bridge, 4C/8T, 95W)22.533811.50435.9518
Core i7-6700K @ 4.00GHz (2015, Skylake, 4C/8T, 91W)17.67738.84584.4978

消費電力

大事な消費電力はどうかと思ってワットチェッカーで計測してみると、起動時19W, 通常時15Wだった。起動時高いのは、HDDを使っているせいだろう。sensors読みで温度的にも40度いくかどうかって感じ。非常に省エネで、こっちのほうが重要なので満足。