記錄一次失敗的系統搶救/折騰經歷

一、事故起因

大概描述下事故起因:
win10/ubuntu16.04雙系統,分別安裝在兩塊256Gb大小的NVME SSD上,以UEFI模式Grub2引導。某天我心血來潮,想要驗證核顯與獨顯是否能一起工作,多次在系統啓動過程中強制下電(作死行爲。。。),終於在一次強制下電後,win10無法啓動了,而且連安全模式都無法進入,一直卡在藍屏界面。
藍屏界面提示如下:

你的設備/電腦需要修復

在這裏插入圖片描述作爲一名技術型宅男,當然不甘心重裝系統,況且還有很多數據不能丟失,於是開始了對win10的搶救之路。

二、WIN10搶救記錄

既然能進入BIOS,說明硬件沒出問題,然後“又提示文件丟失“,因此我猜測很可能是ssd開啓了寫入緩存,在強制下電的過程中數據來不及刷入硬盤,導致一些系統啓動文件受損。

當然一般好一些的ssd都會內置電容蓄電,在斷電時爲I/O爭取最後的時間,只不過這是最後一道防線,不能保證100%不會出問題,雖然我用的是將近1000塊的浦科特m8peg,在多次強制下電後還是中招了。。。

在此也提醒看到這篇文章的朋友:數據無價,請保持良好的電腦使用習慣,千萬不要像我一樣作死,最重要的一點是——要關閉寫入緩存!
廢話不多說了,既然問題已經發生了,那就開始修復吧!

修復NTFS磁盤

進入PE系統,發現系統盤居然無法訪問了,然後用DiskGenu工具查看,磁盤顯示“未格式化”,如下圖:
在這裏插入圖片描述
可能有些人看到這步就要格式化硬盤了,但我推測:強制下電最多導致部分文件受損,數據不可能全部消失,磁盤用工具修復下應該就可以訪問了。

一開始我使用GRUB2下的ntfs-3g工具嘗試修復,發現並沒有什麼卵用。NTFS是Windows家的私有格式,並不開源,還是用WIN10自帶的磁盤修復工具吧,由於原系統已經徹底崩潰(磁盤都無法訪問),只能藉助於WIN10系統安裝U盤,步驟如下:

  • 插入WIN10系統安裝U盤,在BIOS中設其爲啓動項
  • 進入安裝界面,跳過安裝步驟
  • 選擇疑難解答->高級工具->磁盤修復

等修復結束,再進入PE系統,發現系統盤已經可以訪問了,數據也都還在,搶救成功了一小步~

重建WIN10 EFI引導

然而我還是高興地太早了,雖然系統盤可以訪問了,但還是無法啓動WIN10,這次還是卡在藍屏界面,提示如下:

“自動修復”無法你的電腦
日誌文件:D:\WINDOWS\System32\Logfiles\Srt\SrtTrail.txt

找到log文件並打開,錯誤提示如下:

啓動關鍵文件 d:\boot\resources\custom\bootres.dll 損壞

已經很明顯了,啓動文件損壞。
頭疼醫頭、腳疼醫腳,找到問題了就該對症下藥,重建EFI引導吧!

重建EFI引導其實就是將系統盤Windows\Boot\EFI目錄下的文件複製至ESP分區中,當然,我們實際應用的時候不用這麼原始地複製一個一個文件,WIN10已經替我們集成了一個命令(PE下執行),如下:

bcdboot c:\windows /s o: /f uefi /l zh-cn

具體參數要根據實際情況修改,其中:

  • "c:\windows"爲系統盤目錄
  • "/s o:"指定EFI系統分區
  • "/f uefi"指定UEFI啓動方式
  • "/l zh-cn"指定UEFI圖形界面語言爲簡體中文

修復受損系統文件

重建EFI引導後,仍然無法啓動,錯誤提示也和上述一致。

實際上到這一步我已經放棄了,不得已含淚重裝了系統,但是後來根據提示信息在Google搜索,居然找到了Windows官方的QA界面,問題和我99%相似,並且Windows開發者提供瞭解決方案[^1],因此記錄下來,鏈接爲:
Microsoft 支持 - bootres.dll損壞

簡單描述下微軟官方人員的回答,大意爲:

該提示信息意味着系統的.dll文件出現問題,需要重新註冊

這就解釋了即使我重建EFI引導還是無法啓動的原因——系統盤中的EFI相關源文件已經損壞,因此重建的EFI引導也是有問題的。

修復系統文件需要執行以下命令:

cmd /c for %i in (%windir%\system32\*.dll) do regsvr32.exe /s %i
cmd /c for %i in (%windir%\system32\*.ocx) do regsvr32.exe /s %i

若問題依舊需要執行以下命令:

sfc /SCANNOW

後記:
當用Google搜到這個QA界面的時候,我想如果我當時執行這些步驟,應該就大功告成了,也用不着重裝系統,不得不感慨:百度誤我!

使用MediaCreationTool製作WIN10啓動U盤

在失敗的系統搶救之後,不得已只能重裝系統。
其實我已經有win10 17.03的啓動U盤了,但一想到大量的更新就腦殼疼,乾脆用最新的鏡像製作安裝盤,但是驚訝的發現18.09的鏡像竟然無法用UltraISO寫入U盤,上網一查方知18.09鏡像中有單個大小超過4Gb的文件,受FAT32格式限制無法寫入。
不知微軟爲什麼要如此設計,總之是無法用UltraISO製作啓動U盤了。
天無絕人之路,微軟總算提供了官方工具MediaCreationTool製作啓動U盤,下載鏈接:
Download MediaCreationTool
在這裏插入圖片描述
使用很簡單,值得一提的是該工具提供的是一條龍服務——會幫你下載最新的鏡像然後直接寫入U盤,但是卻沒有選擇本地鏡像的入口(意味着我之前下載的18.09鏡像做了無用功)。
不錯,這很“微軟”,就像自動更新一樣,根本不給用戶選擇的餘地。

三、Ubuntu搶救記錄

重建Ubuntu EFI系統分區及EFI引導

在win10崩潰的時候,我想切到ubuntu,發現ubuntu居然也無法啓動,提示:

Could't get size: 0x800000000000000e
MODSIGN: Couldn't get UEFI db list

其實這個問題以前也出現過,原因是win10某些更新會更改EFI系統分區的文件,導致ubuntu的引導文件被破壞。

這種情況只有重建efi引導了,但這也是治標不治本,指不定哪次win10更新又會搞破壞。
有鑑於win10經常更新並禍及EFI系統分區,我決定刮骨療傷,爲ubuntu單獨再建立一個EFI系統分區,讓兩者井水不犯河水。

先介紹下之前ubuntu與win10分區結構吧,兩塊ssd分別安裝了兩個系統,但是共享一個EFI系統分區,Window Boot Mangager與GRUB2“共居一室”,如下圖:
在這裏插入圖片描述
這種分區的弊端在前文已經介紹過了(win10更新破壞ubuntu引導),因此我想做一些調整,如下圖:
在這裏插入圖片描述
看似簡單,其實也要費一番功夫,具體步驟如下:

1. 通過LiveCD(Ubuntu啓動U盤)進入系統

2. 新建EFI系統分區
使用GPart工具在硬盤上劃分一個100Mb大小的分區,分區Label設置爲“Boot,esp”。

3. chroot切換根目錄(LiveCD->待修復的Ubuntu)

  • 將待修復的Ubuntu系統的根分區掛載至/mnt/ubuntu
# mount /dev/nvme1n1p2 /mnt/ubuntu
  • 將新建的EFI系統分區掛載至/mount/ubuntu/boot/efi
# mount /dev/nvme1n1p1 /mount/ubuntu/boot/efi
  • 將LiveCD的虛擬文件系統devfs、procfs、sysfs掛載至待修復的Ubuntu對應目錄下,否則使用chroot後無法訪問一些硬件資源
# mount -o bind /dev /mnt/ubuntu/dev
# mount -o bind /proc /mnt/ubuntu/proc
# mount -o bind /sys /mnt/ubuntu/sys
  • 使用chroot切換根目錄
# chroot /mnt/ubuntu

4. 安裝EFI引導

# grub-install --target=x86_64-efi --efi-directory=/boot/efi

5. 修改fstab文件
使用blkid命令獲取新建EFI系統分區的UUID,然後修改/etc/fstab文件,替換之前EFI系統分區的UUID。

經過一系列動作,Ubuntu順利啓動~

GRUB2命令行引導WIN10

GRUB2是可以引導WIN10的,相反Windows Boot Manager卻不能引導Ubuntu,但是在我安裝GRUB2時,不知爲何沒有自動添加WIN10入口,不過這不打緊,可以先試試GRUB2命令行引導WIN10。

準確地說,GRUB2無法直接引導WIN10,只能通過Windows Boot Manager間接引導,這幾者的加載關係如下:
BIOS->GRUB2->Windows Boot Manager->WIN10

理順了這個關係,就清楚接下來要乾的事情了,以下爲GRUB2命令行引導WIN10所需要執行的命令:

insmod part_gpt
insmod fat
$ set root=(hd0, gpt1)
$ chainloader /efi/Microsoft/Boot/bootmgfw.efi
  • insmod part_gpt &insmod fat
    GRUB2爲了減少自身體積,啓動時一些模塊是默認不安裝的,啓動WIN10需要支持GPT與FAT32格式,這裏我們手動安裝這兩個模塊。
  • set root=(hd0, gpt1)
    該命令效果和shell下的chroot一樣,可以更改當前運行系統的根目錄,需要注意的是(hd0,gpt1)並不是WIN10的系統盤所在分區,而是WIN10的EFI分區,這點在前文已經解釋了(GRUB2無法直接引導WIN10)。
  • chainloader /efi/Microsoft/Boot/bootmgfw.efi
    顧名思義,該命令是一個鏈式裝載啓動工具,通過引導Windows Boot Manager間接引導WIN10

GRUB2添加WIN10啓動項

GRUB2命令行成功引導WIN10,那就意味着可以更進一步——在GRUB2中添加WIN10啓動項了。有想過手動在GRUB2配置文件中添加WIN10的menuentry,卻總覺得不太完美(鄙人強烈的強迫症在作祟)。
有沒有讓GRUB2偵測WIN10自動生成配置文件的方法呢?答案是Yes。
通過GRUB2官方文檔瞭解到如果在第一次安裝時os-probe沒有偵測到WIN10,有兩種方法可以補救:

  • 掛載WIN10的EFI系統分區,然後執行update-grub
  • 先執行lsblk獲取硬盤信息,然後執行update-grub

我用的是第二種方法,果然在update-grub時偵測到了WIN10,然後自動生成了相關的啓動配置。查看/etc/grub.conf文件,自動生成的WIN10配置如下:

### BEGIN /etc/grub.d/30_os-prober ###
menuentry 'Windows Boot Manager (on /dev/nvme0n1p2)' --class windows --class os $menuentry_id_option 'osprober-efi-181C-9F4B' {
	insmod part_gpt
	insmod fat
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root  181C-9F4B
	else
	  search --no-floppy --fs-uuid --set=root 181C-9F4B
	fi
	chainloader /efi/Microsoft/Boot/bootmgfw.efi
}

update-grub 與 grub-mkconfig
grub-mkconfig會讀取/etc/default/grub文件內容,然後通過os-prober掃描所有分區偵測OS,最終生成相關配置並寫入/boot/efi/grub.conf,而update-grub則是一個腳本文件,調用的是grub-mkconfig。

四、小結

生命的意義在於折騰,如果不折騰,那麼跟鹹魚有什麼區別呢?雖然折騰到最後還是重裝了系統,但從中也獲得了許多知識,滿足感爆棚,因此寫下本文,一爲記錄折騰過程防止自己問題重犯、二爲碰到相同問題的朋友們解惑。


參考:

  1. Microsoft 支持 - bootres.dll損壞
  2. GRUB (簡體中文) - ArchWiki
  3. the GNU GRUB manual
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章