安裝最新的 0.14 版 refind 套件時, 畫面閃過 "Creating new NVRAM entry" 的訊息, 下次開機時發現它竟然直接攻佔了我電腦的開機選單! 而且它不是安裝在某顆硬碟的 MBR, 而是裝在更上游的 UEFI NVRAM, 也就是主機板的韌體上。 還好 linux 程式都很有分寸的 , 只是多加了一層選單, 從那裡仍舊可以看到並選取我原來的選單。 (而不是像三十幾年前, 沒品的微軟直接廢了我原本的 OS/2 多重開機選單。) 總之這促使我開始爬文認識 UEFI 韌體管理/EFI variables。 以下測試不必進入 UEFI, 在 linux 命令列底下就可以進行。
近年的主機板上的 UEFI 韌體, 它的一些設定 (例如優先從哪個裝置開機?) 儲存在
nvram 裡面,
就像古代的 BIOS 把設定資訊存在 CMOS 裡面一樣。
在 linux 底下, ls /sys/firmware/efi/efivars
會列出 nvram 裡面的所有變數名稱, 名稱結構是 「變數簡稱-guid」。
但這些檔案的內容並不是單純的 ascii 或 utf8 文字。
若要進一步觀察甚至修改這些變數, 就要安裝兩個套件:
apt install efivar efibootmgr
以下有些動作可能需要 root 的權限。
首先, efivar -l
一樣可以列出 nvram 裡面的所有變數名稱,
跟上述 ls 列出的一樣, 只是名稱結構正好顛倒: 「guid-變數簡稱」。
下面兩個指令可以驗證上述觀察:
ls /sys/firmware/efi/efivars | perl -pe 's/(\w+)-(.{36})$/$2-$1/'
| sort > /tmp/efivars.txt ;
efivar -l | sort | diff - /tmp/efivars.txt
要查看某個變數的值用 -n 選項。 例如:
efivar -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-Boot0000
那麼, 現在就趕快先把所有變數目前的值存起來:
mkdir efivar cd efivar for v in $(efivar -l) ; do efivar -n $v > $v.txt ; done
這些內容的格式看起來有點怪。 查了很久才知道: 根據 UEFI 規格, 很多時候字串都採用 UCS2 編碼; 有些則是二進位值, 例如 *-TimeOut。 別的變數暫時就先算了; 我只想知道其中 boot 相關變數該如何設定, 但卻查不太到解釋 efi boot variable format 的文章, 只找到一篇 (為什麼是來自 wikileaks 的?!) 很簡略文章 NVRAM Variables Explained 以及一篇 開發者的部落格文章。
改搜尋 "efibootmgr tutorial"。 從這兩篇: archlinux 跟
linux config
可以學到很多 efibootmgr 的指令, 例如:
用 efibootmgr --create ...
新增 boot entry、
用 efibootmgr -o 0010,0000...
更改各儲存裝置的開機優先順序、
用 efibootmgr --timeout=...
更改 UEFI 開機選單等待時間... 等等。
我只想把 UEFI 還原成出廠狀態。
用 efibootmgr | grep BootOrder
查出目前最優先的開機選項是 0000,
再用 efibootmgr | grep Boot0000
查出這個選項確實已被 refind 佔領,
於是用 efibootmgr --delete-bootnum --bootnum 0
把它刪掉。
下次再開機時, 第一手主控權又回到我硬碟上原先的
extlinux 手上了!
最後, 趕快按照
archlinux 的教學,
在 fstab 裡面加一句:
efivarfs /sys/firmware/efi/efivars efivarfs ro,nosuid,nodev,noexec 0 0
以便把 /sys/firmware/efi/efivars 目錄改成唯讀
(下次開機才會生效), 以後若再遇到任何軟體
(例如 支援 UEFI 光碟的開機載入程式 rEFInd)
企圖去改 nvram, kernel 就會把它擋下來。
自己確定真的想寫入時, 可以再用
mount -o remount,rw efivarfs /sys/firmware/efi/efivars
暫時開放寫入權限。
用 mount | grep efi
可以查詢目前它是唯讀 (ro) 或可讀寫 (rw) 的。
我認為 linux 系統應該預設把這個目錄掛載成唯讀的, 以免不小心下個 rm 指令或 output redirection 到錯誤的地方, 就毀了 UEFI。 有人 向 systemd 提出建議, 但很遺憾, 被拒絕。 當然, 問題的源頭在於 UEFI 韌體; 也許幫韌體擦屁股並不是 systemd 的責任, 而應該是 kernel? 或是各家 distributions? 我也不知道。 但總之, 這個未解的問題引起了很多 討論。
沒有留言:
張貼留言
因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。