經常聽人說,UEFI取代了BIOS。

據我所致,BIOS是固化在FLASH中的一段代碼,CPU在加電之後從FLASH中載入BIOS,然後完成後續啟動步驟。

我想問的是UEFI的代碼是位於磁碟的ESP分區中的,那麼一定需要有一段代碼去讀取gpt分區表和fat分區格式,然後才能在fat文件系統中找到對應的UEFI文件,然後才能載入UEFI。我覺得CPU不太可能內置處理磁碟分區表和FAT分區的功能。那麼載入UEFI的代碼位於哪裡呢?


謝邀。這個問題答案本來很簡單,但最近由於Boot Guard的引入變得複雜起來了。我們從簡單的答案講起。

簡單答案

UEFI/BIOS的代碼並不在磁碟的ESP分區中,除了極少數嵌入式X86 CPU之外,現在大部分電腦和所有的x86伺服器的UEFI/BIOS都存儲在一塊NOR Flash中,這塊Flash通過SPI介面和南橋PCH相連。當然UEFI的驅動或者app可以放在ESP分區中,本文並不打算討論這種枝節問題。

之所以強調NOR Flash和SPI,是因為答案可能出乎很多人的理解:沒有任何東西載入了BIOS,BIOS是被Shadow到CPU的物理地址空間中的,而這兩個知識點對於理解這個答案十分重要。

我的專欄介紹過NOR Flash:

老狼:雜談快閃記憶體二:NOR和NAND Flash?

zhuanlan.zhihu.com圖標

NOR Flash和我們用在SSD裡面的Flash一個顯著的不同就是它是位元組定址的,而不是塊定址,這就意味著它可以XIP,也就是eXecute in place,我粗陋的翻譯為原地執行代碼,而不需要載入Load到某塊內存中執行。這個特性十分重要,因為在上電啟動後,內存初始化還沒有進行,沒有內存可供使用,雖然我們可以將Cache偷過來做內存用一段時間(Cache As RAM,CAR),但總是沒有直接用起來方便。

SPI介面十分方便,速度比老的LPC快很多。SPI在南橋晶元中接入到SPI控制器上。SPI控制器在南橋上電後負責翻譯地址(Address Decode),將Reset Vector附件的4~32MB(可調)地址訪問,翻譯成SPI指令,從NOR Flash中得到相應指令和數據。

好了,我們一起來梳理一下。

  1. CPU上電後,內核Core需要Reset Vector的代碼,它把改地址放到地址匯流排上;
  2. Uncore的DMI控制器預設decode這塊空間,它把該請求通過DMI匯流排發給南橋;
  3. 南橋的SPI控制器預設decode這塊地址空間,它用SPI匯流排問SPI Flash晶元要該內容;
  4. SPI晶元相應該請求,返回內容;
  5. SPI控制器相應請求,當二傳手返回內容;
  6. DMI控制器相應請求,當三傳手返回內容;
  7. CPU內核收到指令,開始解碼執行。

這樣一個64B的信息有了,直到運行下一個64B,再循環往複。可以看出,並沒有人載入整個BIOS,而是一點點通過地址decode慢慢運行的,這個過程我們叫做Shadow。

事情複雜起來了

由於安全性的問題,近期的電腦幾乎都引入了Boot Guard的特性,我在這篇文章中有介紹:

老狼:什麼是Boot Guard?電腦啟動中的信任鏈條解析?

zhuanlan.zhihu.com圖標

因為Boot Guard要驗證BIOS的一致性,需要讀取大部分BIOS內容,所以現在是ACM會將BIOS整個載入到Cache As RAM進行驗證,驗證通過後,就會直接運行Reset Vector。所以,現在很多情況下,答案變成了Boot Guard ACM會載入UEFI/BIOS。

歡迎大家關注本專欄和用微信掃描下方二維碼加入微信公眾號"UEFIBlog",在那裡有最新的文章。

用微信掃描二維碼加入UEFIBlog公眾號

首先簡單說明下,現在所說的UEFI就是BIOS,也是放在一塊8M的Flash中。而硬碟中也有一塊EFI分區,這個分區存放的是引導程序,拿linux來舉例就是GRUB。所以2者不要混淆。

那麼接下來,我們在詳細分析下,系統的整個啟動過程,以及如何載入UEFI,啟動操作系統。

開機

用簡單的語言來描述就是,電腦按下開機鍵之後做了什麼?

1. 我們先看下CPU的結構,之前intel的CPU是由南北橋組成的,在我做固件的時候,北橋就已經沒有了,北橋主要是做內存控制器用途的,由於同樣是高速匯流排,所以集成到CPU裡面了,只留下了南橋,南橋主要是低速匯流排,例如串口,USB介面,硬碟,顯示器介面等(現在南橋也已經集成在CPU里了,所以後面統一稱CPU),其中就包括我們的BIOS,之前的叫法是BIOS,現在intel升級了一下軟體架構,使得BIOS更加靈活,類似一個小的操作系統,改名叫UEFI,然後扶植台灣親兒子做這個架構,成為了開機啟動的事實標準。

2. 實際上開機啟動之後,CPU會從外部地址去取指令,intel的CPU是從FFxxxxxx的某個地址,而ARM則大部分是從0地址取指令。所以大部分固件也就是UEFI(ARM叫uboot)會把啟動程序放在這個地址,這段代碼大部分都是彙編代碼,做一些簡單的初始化,有人就問了,為什麼不用C語言呢,因為這時候系統還沒有初始化堆棧,而C語言是需要堆棧的,而彙編則不需要,做完簡單的初始化之後,UEFI會把cache當做堆棧使用,然後初始化內存,之後會把程序搬運到內存中,之後就是初始化各種硬體了,例如USB介面,顯卡,硬碟等。也就是說,CPU每次啟動都會從固定的地址取指令來初始化CPU,然後初始化整個硬體設備

啟動操作系統

UEFI啟動完成之後,一般會有一個選擇啟動項的界面,選擇從那個硬碟或者操作系統啟動。

1. 這一部分選擇好之後,BIOS直接會跳轉到硬碟的MBR分區,BIOS就已經結束了,以後沒BIOS什麼事情了。程序跳轉到MBR分區(MBR是硬碟的第一個分區)之後,就會載入操作系統的引導程序,實際上這一部分也是相當複雜,因為MBR一個分區只有512個位元組,對普通的程序來說太小了,所以這一部分實際上也是一些指針,讓程序跳轉到真正的引導程序去啟動,類似一個嚮導的功能。隨著PC的發展,上面的引導方式捉襟見肘,首先的一個問題是MBR分區壞了怎麼辦,那麼整個盤就廢掉了,因為沒法引導操作系統了。

2. 那麼UEFI是如何解決這個問題的呢?UEFI的架構好就好在,支持了EFI文件系統,也就是說,我不關心文件在那個扇區,我只關心文件,這樣引導程序可以放在第一個分區MBR,也可以在第100個,這就解決了上面的問題。因此每次安裝操作系統的時候都會多出一個EFI分區(大部分對用戶是隱藏的),這個分區的作用就是安裝引導程序,以linux來舉例子就是安裝grub,UEFI啟動之後,直接讀取硬碟的EFI文件系統,然後啟動grub,再由grub去引導操作系統。操作系統啟動之後就接管了整個硬體,用戶就可以在操作系統下工作了。而windows也有對應的引導程序,只不過這一部分沒有公開,也是在EFI分區[1]

總結

系統開機之後會從UEFI啟動,初始化整個硬體,之後會跳到硬碟的EFI分區,啟動操作系統引導程序,之後操作系統開始工作。

榮耀9X 麒麟810 4000mAh續航 4800萬超清夜拍 6GB+64GB京東¥ 1189.00去購買?

參考

  1. ^EFI分區 http://cn.wondershare.com/recover-data/all-you-need-to-know-about-the-efi-system-partition.html


你按下電源開關後,ec和南橋通訊確認之後給電源發信號上電,南橋在確認後給cpu上電,然後cpu緩存初始化再初始化內存,最後從on die rom讀取rest vector,載入uefi


問題出在「UEFI的代碼是位於磁碟的ESP分區中的」,ESP 中存的是 UEFI 應用程序,載入 UEFI 應用程序的程序是 UEFI 固件,也是存放在快閃記憶體晶元里的。


CPU上電開始會把除CS寄存器之外的寄存器全部清零,CS寄存器被置成0xFFFF,而CS:IP所指向的地址空間是存放BIOS/UEFI ROM映射成的物理地址,這樣定址系統就從BIOS /UEFI ROM里把入口地址裝載進CPU里開始執行,這個是CPU上電後的第一條指令,之前可能有些片面的認為定址只能針對內存,其實應該不然,計算機的體系結構里應該除內存外的其他外設也可以通過定址操作訪問得到,比如BIOS /UEFI ROM也是在定址空間中,一些IO外設也是在同樣的定址空間里。


UEFI固件儲存在主板的一塊UEFI ROM晶元(NOR Flash晶元)上。這個UEFI ROM掛在南橋的LPC/SPI下。這個UEFI ROM的大小為幾MB-幾十MB。UEFI絕大部分功能放在UEFI ROM里。

UEFI啟動的階段大致有SEC-&>PEI-&>DXE-&>BDS-&>TSL-&>RT,還有SMM、CSM(CSM是UEFI的可選項)。

當系統Power On後,執行SEC階段,將CPU從實模式轉為長模式,SEC使用CPU Cache作為RAM(就是Cache as RAM,CAR)。此時內存還未被初始化。

PEI(Pre-EFI)階段主要執行內存控制器(內存控制器集成在北橋中,後來Intel和AMD把北橋集成在CPU中)和內存的初始化,為接下來的DXE階段做準備。

DXE(Driver Execution Environment)階段執行EFI Drivers(包括UEFI固件內置的EFI Drivers)和EFI Applications。DXE階段大部分代碼是用C語言寫的。DXE階段執行大部分的系統初始化工作。DXE階段載入的EFI Driver和EFI Application其實是PE格式的可執行文件。

BDS(Boot Device Selection)是DXE階段的一部分,BDS階段檢測、初始化啟動設備(如儲存設備、顯卡、網卡),最後從某個Boot Device啟動OS(其實就是從硬碟或網卡載入EFI Application文件)。

ACPI和SMBIOS的初始化,在PEI、DXE階段都有涉及。當載入OS後,UEFI的SMM程序仍然在SMRAM運行。

UEFI ROM被稱為FD(Flash Device),FD包含的EFI Driver、EFI Application等模塊文件稱為FV(Flash Volume)。

有些PCIe設備(如顯卡、網卡、RAID卡)有自己的固件晶元,UEFI固件在BDS階段載入PCIe設備的Option ROM。

Intel Boot Guard是先校驗IBB的數字簽名(把IBB載入到CPU Cache中),再由IBB校驗OBB的數字簽名。IBB就是PEI和少部分DXE;IBB作用同Boot Block,當BIOS損壞但沒有損壞Boot Block的時候,Boot Block程序可以從U盤恢復BIOS。

有些OEM(如惠普)會把部分EFI Application、EFI Driver(比如UEFI診斷程序)儲存在ESP中,以降低成本。


我把問題這樣改一下可能就比較容易理解的

我想問的是EFI的程序是位於磁碟的ESP分區中的,那麼一定需要有一段代碼去讀取gpt分區表和fat分區格式,然後才能在fat文件系統中找到對應的EFI程序,然後才能載入UEFI兼容的操作系統。我覺得CPU不太可能內置處理磁碟分區表和FAT分區的功能。那麼載入UEFI(BIOS)的代碼位於哪裡呢?

BIOS在CPU所支持的存儲設備里,可以是SPI,可以是EMMC/SDCARD,也可以是完全內置的bootrom。


還是bios咯,只不過從載入mbr變成載入efi


UEFI是個統稱,按照問題來看,可以劃分為UEFI執行環境,和在磁碟上的作為OS Loader 的 UEFI App。

App 由UEFI環境來載入,UEFI環境就是所謂的BIOS,通常固化在主板上。

簡單說磁碟上你看到的efi文件僅僅是整個uefi引導的最後階段。在這之前固化在主板上的uefi固件已經跑很多東西了。


推薦閱讀:
相关文章