本文旨在簡單的介紹一下DXE階段的工做原理:linux
UDK2015的開源代碼下載:https://github.com/tianocore/tianocore.github.io/wiki/EDK-IIgit
DXE階段是UEFI系統的最主要的組成部分,github
1.DXE階段主要由兩部分組成:DXE內核 + 模塊;編程
2.DXE內核提供了最基本的一些功能,好比Protocol的管理,事件的管理等等(DXE內核提供的基本功能稱爲服務);api
3.經過加載各類模塊擴展其餘的功能;框架
4.DXE階段的核心概念:Service、Protocol、Handle(Handle和Protocol組成一個二維鏈表,protocol提供的接口相似於內核符號表中的函數;Service相似於linux kernel api);函數
5.DXE內核在post過程當中會加載各類模塊,每一個模塊會安裝不一樣的Protocol(Protocol相似於面向對象編程裏面的類),用來擴展系統支持的功能;post
內核提供的基本Service:spa
1 // 2 // DXE Core Module Variables 3 // 4 EFI_BOOT_SERVICES mBootServices = { 5 { 6 EFI_BOOT_SERVICES_SIGNATURE, // Signature 7 EFI_BOOT_SERVICES_REVISION, // Revision 8 sizeof (EFI_BOOT_SERVICES), // HeaderSize 9 0, // CRC32 10 0 // Reserved 11 }, 19 (EFI_CREATE_EVENT) CoreCreateEvent, // CreateEvent 20 (EFI_SET_TIMER) CoreSetTimer, // SetTimer 21 (EFI_WAIT_FOR_EVENT) CoreWaitForEvent, // WaitForEvent 22 (EFI_SIGNAL_EVENT) CoreSignalEvent, // SignalEvent 23 (EFI_CLOSE_EVENT) CoreCloseEvent, // CloseEvent 24 (EFI_CHECK_EVENT) CoreCheckEvent, // CheckEvent 25 (EFI_INSTALL_PROTOCOL_INTERFACE) CoreInstallProtocolInterface, // InstallProtocolInterface 26 (EFI_REINSTALL_PROTOCOL_INTERFACE) CoreReinstallProtocolInterface, // ReinstallProtocolInterface 27 (EFI_UNINSTALL_PROTOCOL_INTERFACE) CoreUninstallProtocolInterface, // UninstallProtocolInterface 28 (EFI_HANDLE_PROTOCOL) CoreHandleProtocol, // HandleProtocol 29 (VOID *) NULL, // Reserved 30 (EFI_REGISTER_PROTOCOL_NOTIFY) CoreRegisterProtocolNotify, // RegisterProtocolNotify 31 .... 56 };
上面是DXE內核提供的功能。指針
但也有些Service,內核沒有提供具體的實現,只是聲明瞭接口:
EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = { { EFI_RUNTIME_SERVICES_SIGNATURE, // Signature EFI_RUNTIME_SERVICES_REVISION, // Revision sizeof (EFI_RUNTIME_SERVICES), // HeaderSize 0, // CRC32 0 // Reserved }, (EFI_GET_TIME) CoreEfiNotAvailableYetArg2, // GetTime (EFI_SET_TIME) CoreEfiNotAvailableYetArg1, // SetTime (EFI_GET_WAKEUP_TIME) CoreEfiNotAvailableYetArg3, // GetWakeupTime (EFI_SET_WAKEUP_TIME) CoreEfiNotAvailableYetArg2, // SetWakeupTime (EFI_SET_VIRTUAL_ADDRESS_MAP) CoreEfiNotAvailableYetArg4, // SetVirtualAddressMap (EFI_CONVERT_POINTER) CoreEfiNotAvailableYetArg2, // ConvertPointer (EFI_GET_VARIABLE) CoreEfiNotAvailableYetArg5, // GetVariable (EFI_GET_NEXT_VARIABLE_NAME) CoreEfiNotAvailableYetArg3, // GetNextVariableName (EFI_SET_VARIABLE) CoreEfiNotAvailableYetArg5, // SetVariable (EFI_GET_NEXT_HIGH_MONO_COUNT) CoreEfiNotAvailableYetArg1, // GetNextHighMonotonicCount (EFI_RESET_SYSTEM) CoreEfiNotAvailableYetArg4, // ResetSystem (EFI_UPDATE_CAPSULE) CoreEfiNotAvailableYetArg3, // UpdateCapsule (EFI_QUERY_CAPSULE_CAPABILITIES) CoreEfiNotAvailableYetArg4, // QueryCapsuleCapabilities (EFI_QUERY_VARIABLE_INFO) CoreEfiNotAvailableYetArg4 // QueryVariableInfo };
以EFI_RUNTIME_SERVICES->ResetSystem()爲例,不一樣的平臺(好比x86與ARM),重啓系統的實現方式是不同的,因此UDK代碼裏面沒有給出具體的實現。在實際項目中,經過平臺BSP代碼提供的模塊來安裝這個實現:
// // Hook the runtime service table // SystemTable->RuntimeServices->ResetSystem = Cf9ResetSystem;
1 VOID 2 EFIAPI 3 Cf9ResetSystem ( 4 IN EFI_RESET_TYPE ResetType, 5 IN EFI_STATUS ResetStatus, 6 IN UINTN DataSize, 7 IN CHAR16 *ResetData OPTIONAL 8 ) 9 { 10 //不一樣平臺的具體實現;
11 }
UDK整個系統的代碼框架可描述以下:
1.內核聲明瞭整個系統必須實現的接口(依據UEFI/PI規範);
2.一部分(最最基本)的接口的實現由內核提供,一部分接口的實現由於跟平臺有關,因此由平臺代碼提供;
3.經過模塊安裝各類各樣的擴展功能(protocol);
4.整個代碼框架是微內核結構,內核只提供基本的功能,模塊經過安裝protocol來提供其它功能;
5. 內核實現了框架,並提供API,驅動程序調用內核提供的API把本身實現的接口(protocol)安裝到系統中,系統使用統一的接口訪問不一樣的實現。
6.DXE最後會把控制權交給BDS:
某個DXE driver會安裝下面的protocol,用來提供BDS的入口,DXE到BDS體現了內核經過統一接口訪問不一樣實現的思想。
模塊舉例:
UDK裏面的模塊舉例:(這裏的模塊沒有follow UEFI Driver Model)
UEFI Spec裏面經過EFI_IMAGE_ENTRY_POINT 這個函數指針類型定義了 UEFI Image的入口點的形式(包括返回值和參數)
Linux裏面的模塊舉例: