小華的部落格: Extensible Firmware Interface ,EFI 簡介

搜尋此網誌

網頁

星期五, 4月 27, 2007

Extensible Firmware Interface ,EFI 簡介

Extensible Firmware Interface ,EFI 簡介 by Harrison

Extensible Firmware Interface (EFI) 是一個規範,他規範了一個介面,界於作業系統(例如: Windows)與平台韌體(Platform firmware)之間的一個橋樑。 EFI的改進被用來取代傳統BIOS的介面(這個傳統的介面被稱之為IBM PC compatible PC 的BIOS或稱之為Legacy BIOS).

­最初EFI是由Intel 所主導發展,目前則由UEFI論壇(Unified EFI Forum) 的會員一起共同維護,這便是眾所皆知的UEFI (Unified EFI,統一的EFI).

發展歷史 History
最初EFI發展動機是為了在1990年中的Intel-HP Itanium 系統,當時的PC BIOS有一個限制(支援16 bit 的處理器模式,1MB 位址空間與AT 硬體架構),而這個限制使的他無法支援大型伺服器平台的系統Intel-HP Itanium。 最初的時候Intel 只是為了解決這些BIOS啟動時的限制,後來就乾脆改變它的名稱,且稱之為EFI。

EFI specification 1.02 在2000年12月的時候由Intel發行 (Version 1.01 則是Intel 最初發行的版本,但是它裡面有一些錯誤存在。)

EFI specification 1.10 在2002年12月1日發行,他包含了 EFI driver model 增強版。
到了 2005年, Intel 將這個版本貢獻給 UEFI Forum來幫助大家討論,藉以提升EFI開發環境以及提升他的功能。 所以將EFI改稱為 Unified EFI (UEFI)來代表這個改變。

而UEFI Forum 目前2007年1月7日的最新版本是UEFI specification version 2.1 。它增加了cryptography,network authentication, IPv6 support和User Interface 架構(簡稱 UEFI使用者介面,或稱HII)。

EFI specification 所定義的介面中包含platform information的Data tables還有啟動服務(Boot Services)與Runtime services (例如如何去啟動OS loader 或是啟動 ㄧ個EFI-aware OS)。

另外像是原本就存在於PC BIOS中的其他類型的增強型BIOS(像是SMBIOS或是ACPI )也都可以存在於EFI之中,因為他們並沒有使用16-bit runtime interface去服務他們。

Services
EFI 定義了啟動服務( boot services),這些服務包含了文字與圖形支援,這些支援可以針對不同的設備(device),匯流排(bus),檔案服務(file services),Block…等, 還有一些runtime services 就像是date, time 和 NVRAM services.

Device drivers
EFI針對標準設備驅動程式的增加部份,它提供了處理器-非依賴的設備驅動程式環境(Processor-independent device driver environment) 稱之為EFI Byte Code 或 EBC。依照UEFI 規範中的系統需求中提到,系統需要裝設一個翻譯器(interpreter)來提供EBC Image 的裝載(resides in)或是載入(Loaded into)進去這個環境。

因此,EBC會類似被模擬成Open Firmware的樣子。而這個Open Firmware(他是一個硬體-非依賴韌體,Hardware-independent firmware)是就像是使用在 PowerPC-架構的 Apple Macintosh 電腦或是 Sun Microsystems SPARC 電腦,或是其他也在使用Open Firmware的電腦。

一些非EBC(non-EBC architecture EFI device drivers types)架構的EFI 設備驅動程式型態則有一個介面來支援OS對他們的使用。

這些介面可以允許OS去依賴EFI所提供的一些基本設備驅動程式(像是圖形驅動程式,網路驅動程式的支援)來初始化一些設備,直到OS所需的驅動程式全被載入為止。

Boot Manager
EFI boot manager 也被使用來選擇和載入一個作業系統(Operating system),移除則需要決定一個Boot Loader的管理機制 (Boot Loader變成EFI 應用程式的類型),在Framework架構中是屬於Boot Device Select,BDS階段。


Disk Support
除了標準PC磁碟分割(Disk partition scheme)架構Master boot record (MBR)之外, EFI 還增加了一個新的支援 GUID Partition Table (GPT), 而這個新的支援則不受到標準MBR的侷限。 在EFI specification 並沒有描述你要使用哪一種的file system; 而典型的EFI在實作上則內定支援使用 FAT32 的檔案系統。

The EFI Shell
EFI 社群(community)建立了一個開放式源碼(Open Source)與介殼程式環境(Shell environment),是使用者與作業系統溝通的程式,負責解譯及執行使用者下達給作業系統的指令。

­所以EFI Shell並不是直接的啟動進入到OS,因此在某些情況之下,使用者可以進入到EFI shell。而這個shell是一個EFI application,它可以直接存在於platform ROM(直接燒入在裡面),或是在有驅動程式的ROM的設備上面(透過驅動程式來載入EFI Shell)。

像在MacBook (Apple 的Intel CPU架構的筆記型電腦),你可以把EFI shell 應用程式放在USB隨身碟,而在開機的時候按著"Option",然後就會看到一個選擇開機項目的畫面,選擇你的USB隨身碟,那麼就可以看到一個長的很像DOS的畫面,而這個畫面就是EFI Shell。

而這個Shell可以被使用來執行一個EFI 的應用程式,像是 setup, OS install, diagnostic(診斷分析程式)或是Configuration utilities和System flash updates…等,他也能直接的播放CDs 或是DVDs ­而不需要進入到一個完整的OS環境底下,它提供了一個適當的環境來開發EFI應用程式。另外Shell commands也可能可以用來複製,搬移檔案或是目錄(如果你的Shell 有支援),而設備驅動程式也可以利用他去載入或是卸載,而一個完整的TCP/IP 堆疊(TCP/IP 7層架構)也可以使用EFI Shell被完整的使用。

簡單說就是EFI Shell提供了一個不需要進入OS環境也可以處理你需要的工作的一個環境。最後EFI shell支援腳本,而他的副檔名是 .nsh files,他就像是DOS下的批次檔( batch files)。
Shell Command的指令名稱繼承了DOS command interpreter 或是 Unix shell(操作起來像是混合體,有時出現DOS指令的名稱,有時是Unix的名稱) ,­而EFI Shell其實就是可以看作成在BIOS裡面的一個DOS環境。

Extensions
EFI延伸功能之中所描述,EFI可以從任何虛擬的非揮發性儲存設備載入並且連接到電腦之中,例如一個original equipment manufacturer (OEM) 廠商在賣系統的時候將EFI 分割區放硬碟中,而要將這些功能載入的程式則放在主機板上的ROM之中,簡單說就是BIOS ROM裡面的程式可以去硬碟把EFI 功能載入出來執行,例如一些測試程式放在硬碟,然後EFI開機的時候去硬碟讀取這些程式出來執行。

Intel Platform Innovation Framework for EFI
Intel 在其平台上為了EFI去建立了一個新框架(Framework),而這個框架的最初代號叫做Tiano,這個框架非常的完整,它包含了EFI對原本傳統韌體的所有支援,他也可以透過所謂的compatibility support module(CSM)來支援傳統的PC BIOS,簡單說就是傳統BIOS能做的EFI也能做,但是不是完整支援就要看CSM支援的程度。

特別是,這個框架包含了在Power-On後,所有必要的初始化步驟去初始化一個平台(Platform);但是這些步驟的運作並沒有被定義在EFI specification內,而是被定義在 Platform Initialization Specification內的某個章節。

Intel 並沒有將這個架構完整的開放給一般的End-User知道,他只有開放這些資訊給一些獨立的BIOS 廠商(稱之為IBV),像是安邁 (American Megatrends ,AMI) 或是系微(Insyde Software) …等的BIOS韌體供應商。

而在TianoCore project(也就是所謂的EFI Developer Kit ,EDK)的Open source之中,會提到如何去開發這個Framework。這個開發工具中含括了EFI的一些硬體初始化的程式碼(只針對一些硬體,但並不包含韌體本身) ,至於這些程式碼的授權包含BSD licenseEclipse Public License…等。

而Tiano是為了取代BIOS的一種框架,所以透過EFI可以讓PC的設備自己撰寫一個驅動程式來管理這個設備。而對於開放原始碼來說,這也代表大家可以從TianoCore.org 下載這個專案,然後以BSD(Berkley Software Distribution)的授權方式來生產你的產品。BSD的授權,你自己去修改它的軟體並且發展出屬於你自己的產品,但BSD並不會去要求你把修改的地方公開出來,而這種方法會有助於你去保護你的智慧財產權。

Platforms that use EFI or the Framework
最早使用EFI 的平台式 Intel的第一個Itanium 工作站和伺服器,他們支援EFI 1.02。 接著是Hewlett-Packard的第一個 Itanium 2 系統(2002年發表),支援EFI 1.10; 而這些系統都可以啟動 Windows, Linux, FreeBSDHP-UX

不管是Itanium或是 Itanium 2 系統,他們在出貨的時候都是使用EFI compliant firmware,且須遵照DIG64 specifications。

2003的11月, Gateway 介紹他們的Gateway 610 Media Center,第一個x86 Windows-based 的電腦系統使用了這個框架(Framework),而韌體供應商則是 Insyde Software's InsydeH2O。而這個韌體依舊是依靠賴傳統BIOS相容介面的方式去實作出這個框架來啟動微軟系統,簡單說就是EFI 的框架去模擬成傳統BIOS,因為Windows並不認識EFI,所以利用EFI框架做出模組(Module)方式去符合目前x86 架構。

在2006年1月,Apple Computer 販售了屬於他們第一次使用 Intel-based的Macintosh電腦, 這個系統使用了EFI和新框架Framework來取代了原本他們在Power PC-Based 一直以來都在使用的 Open Firmware,而在 2006年4月5日, Apple 公佈了一個 Boot Camp 應用程式,這是一個非破壞性的分割工具(non-destructive partitioning tool)去幫助Apple的使用這去安裝Windows XP驅動程式甚至是系統到麥金塔的電腦之中。

而同時,Apple的韌體的也做了更新支援,讓傳統的BIOS支援去它的EFI實作。在此之後,所有的麥金塔系統(Intel-Based)也都是使用使這種韌體(Firmware)出貨。 現在所有目前的Macintosh systems 也都可以啟動傳統的作業系統Windows XP,簡單說就是WindowsXP不認識EFI,而Apple機器內如果裝了Windows XP就必須使用Legacy BIOS方式去啟動Windows XP,因此Apple更新了EFI的Firmware支援,去模擬出一個傳統的BIOS介面來支援,應該也是叫做CSM。

從2005年之後,幾乎大多數的Intel 主機板都開始出貨這種支援新的框架架構的主機板的韌體(Framework-based firmware)。現在像是一些新的mobile,,desktop和 server 產品,在2006年起,也都開始使用這種框架。

自2005起,EFI也開始被實作在非PC架構的系統上,像是嵌入式系統,像是 embedded systems based 的 XScale cores。

而EDK 還包含了NT32 的目標(Target),也就是說它允許EFI Frimware和EFI Application 去執行一個Windows 應用程式。


Security and freedom concerns
According to Ron Minnich, the lead developer for LinuxBIOS, one of the stated goals of EFI is to protect hardware vendors "intellectual property"[15]. This raises security concerns and notably makes creating a free software BIOS impossible.
EFI could be used to create a "DRM BIOS", thus letting vendors build computers which limit what the user can do.

有關於自由軟體運動v.s EFI 請參考下列網站說明:
http://taiwan.cnet.com/enterprise/technology/0,2000062852,20098242,00.htm

Reference
維基百科
CNET

2 則留言:

匿名 提到...

在網路上有看到電腦主機板廠商徵求EFI工程師,請問與bios工程師有何不同??EFI工程師的工作內容是什麼??要具備哪些技能??~~^_^

匿名 提到...

//**********************************************************************
//**********************************************************************
//** Demo code for PCI configuration space I/O access program **
//** By Lawrence 2009/11/20 **
//**********************************************************************
//**********************************************************************

#include "efi.h"
#include "efilib.h"

#define Not_Found_Me 0x00000000
#define Found_Me 0x00000001

static EFI_STATUS WaitForKeyOrReset(VOID)
{
EFI_STATUS Status;
EFI_INPUT_KEY key;
UINTN index;

for(;;) {
Status = ST->ConIn->ReadKeyStroke(ST->ConIn, &key);
if (Status == EFI_NOT_READY)
BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &index);
else
break;
}
if (!EFI_ERROR(Status)) {
if (key.ScanCode == SCAN_ESC)
RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
}

return Status;
}

UINTN
AccessPciConfig (
IN EFI_PCI_IO_PROTOCOL *PCI_DEVICE_TARGET
)
{
UINT8 i;
UINTN PCI_ATTR[4];
UINT8 PCI_REG[4], pci_offset=0;

//get device attr
PCI_DEVICE_TARGET->GetLocation(PCI_DEVICE_TARGET,PCI_ATTR,PCI_ATTR+1,PCI_ATTR+2,PCI_ATTR+3);
if ((PCI_ATTR[1] == 0x00) && (PCI_ATTR[2] == 0x1e) && (PCI_ATTR[3] == 0x00)){
Print (L"Device found at BUS = %02x DEV= %02x FUN= %02x \n",PCI_ATTR[1],PCI_ATTR[2],PCI_ATTR[3]);
ST->ConOut->SetAttribute (ST->ConOut, EFI_TEXT_ATTR (EFI_GREEN, EFI_BLACK));
//print register value
for (i = 0;i < 4;i++)
{
PCI_DEVICE_TARGET->Pci.Read (PCI_DEVICE_TARGET,0,pci_offset,4,PCI_REG);
Print(L"Register0x%d value = %02x \n",i, PCI_REG[i]);
}
Print(L"\n");
ST->ConOut->SetAttribute (ST->ConOut, EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK));
return Found_Me;
}

return Not_Found_Me;
}

EFI_STATUS
InitializePciApplication (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE *Handle;
UINTN BufferSize, Result;
UINTN NoHandles, Index;
EFI_PCI_IO_PROTOCOL *PCI_DEVICE_TARGET;

//
// Initialize the Library.
//
InitializeLib (ImageHandle, SystemTable);
//
// Find the PCI driver
//
Handle = NULL;
BufferSize = 1;
do
{
if (Handle)
{
FreePool (Handle);
}

Handle = AllocatePool (BufferSize);
Status = BS->LocateHandle (ByProtocol, &PciIoProtocol, NULL, &BufferSize, Handle);

} while (Status == EFI_BUFFER_TOO_SMALL);
ASSERT (!EFI_ERROR(Status));

NoHandles = BufferSize / sizeof(EFI_HANDLE);
Index = 0;
ST->ConOut->ClearScreen (ST->ConOut);
Result = Not_Found_Me;
do
{
if(Index == NoHandles - 1)
Index=0;
else
Status = BS->HandleProtocol (Handle[Index], &PciIoProtocol, (VOID*)&PCI_DEVICE_TARGET);
Print(L"THIS IS DEVICE %d \n",Index);
if (!EFI_ERROR(Status))
{
Result = AccessPciConfig(PCI_DEVICE_TARGET);
//- Print(L"Again now Result is %x \n",Result);
}
Index++;
} while(Result == Not_Found_Me);

Print(L"Please hit any key to exit this image.");
WaitForSingleEvent (ST->ConIn->WaitForKey, 0);

return EFI_SUCCESS;
}