1. 在Driver.c中的DxeMain(), 首先會去Locate三個Protocol, 分別是EFI_HII_CONFIG_ROUTING_PROTOCOL, EFI_HII_DATABASE_PROTOCOL以及EFI_FORM_BROWSER2_PROTOCOL.
2. 找到gST->ConsoleInHandle的EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
3. 檢查BootMenu的Protocol是否已安裝, 如果還未安裝, 表示正在Post階段, Setup還沒初始化, 這時候需要先註冊Event, 等EFI_HII_PLATFORM_SETUP_FORMSET安裝後, 再呼叫BmInitSetupMenu(), 註冊完之後順便安裝BootMenu的Protocol.
4.1. (XP版)在SetupBootMenu.c中, BmInitSetupMenu()首先會透過BmLoadBootOptions()去載入所有Boot Option. 接著呼叫BmInitSetupMenuStrings()以及BmInitSetupMenuForm(). 最後透過HiiLibCreatePackageListDriverHandle()建立HII Driver Handle, 透過HiiLibCreatePackageListFromPackages()建立HII Package List.
4.2. (MB3版)在BootIii.c中, BmInitSetupMenu()首先會透過CreateHiiDriverHandle()建立HII Driver Handle. 接著呼叫PreparePackageList()以及NewPackageList()去安裝VFR Form. 接著Locate SCT_BDS_SERVICES_PROTOCOL. 透過Protocol呼叫GetBootList().
4.2.1. BootManager會先InitializeLoadOptions(), Load Option又可分成兩種, 一種是Boot, 另一種是Driver.
5. 如果Setup Menu的Boot Page沒有被執行, 那麼BootManager就會來執行BmInitMenu().
6. 在Menu.c中, BmInitMenu()首先會執行BootMenu.c的BmInitBootMenu()去初始化Boot Menu畫面的設定值. BmInitMenu()也會執行AppMenu.c的BmInitAppMenu()去初始化App Menu畫面的設定值. 接著透過BootOption.c的BmLoadBootOptions()去Load所有Boot Option. 接著執行BmInitAppMenu()和BmLoadAppOptions(). 最後透過HiiLibCreatePackageListDriverHandle()建立HII Driver Handle, 透過HiiLibCreatePackageListFromPackages()建立HII Package List (這段Code類似SetupBootMenu的部分, 但在這裡只有安裝String而已, 沒有安裝Form.
6.1 當BootOption.c執行BmLoadBootOption()時, 會透過BDS_SERVICES_PROTOCOL->GetBootList()去取得Boot List的起點.
7. 最後透過BmDrawMenu()去畫BootMenu. 用BmInteractMenu()去接受Keyboard按下的鍵來做反應.
2011年9月23日 星期五
2011年7月14日 星期四
Hii Setup Menu
1. 建立INF file, 如Sample.inf. 給一組GUID並設定為BS_DRIVER.
2. 建立一個Header file - Vfr.h, 並設定一組Formset GUID. 另外須設定一個Form Id.
3. 建立一個VFR file - Sample.vfr, 並將Formset GUID設定進來.
4. 建立Sample.c, 這裡有一些步驟須進行:
a. 先宣告一個extern的陣列資料, 命名規則是以VFR檔名+Bin[].
b. 宣告一個extern的字串陣列資料, 命名規則是以INF檔名+Strings[].
c. 須設定一組GUID, 此GUID須宣告在DEF file, 之後會安裝給HII Protocol.
d. 進入DxeMain, 首先要Locate EFI_HII_DATABASE_PROTOCOL.
e. 再來Locate EFI_HII_CONFIG_ROUTING_PROTOCOL.
f. 把Bin[]與Strings[]與Formset GUID包成EFI_HII_PACKAGE_LIST_HEADER.
g. 利用HiiLibCreatePackageListDriverHandle產生一個Driver Handle.
h. 將產生出來的Driver Handle以及EFI_HII_PACKAGE_LIST_HEADER,
加到HII Database裡面去. 並產生一個HII Handle.
i. 安裝EFI_HII_CONFIG_ACCESS_PROTOCOL到Driver Handle裡面去.
此Protocol包含了三個Callback Function. 包含:
(1). ExtractConfig. 進入Setup Menu時會呼叫.
(2). RouteConfig. 離開Setup Menu時會呼叫.
(3). Callback. 頁面切換時會呼叫.
j. 將SCT_FORM_SET_PROTOCOL的資料填入, 並安裝給Driver Handle.
2. 建立一個Header file - Vfr.h, 並設定一組Formset GUID. 另外須設定一個Form Id.
3. 建立一個VFR file - Sample.vfr, 並將Formset GUID設定進來.
4. 建立Sample.c, 這裡有一些步驟須進行:
a. 先宣告一個extern的陣列資料, 命名規則是以VFR檔名+Bin[].
b. 宣告一個extern的字串陣列資料, 命名規則是以INF檔名+Strings[].
c. 須設定一組GUID, 此GUID須宣告在DEF file, 之後會安裝給HII Protocol.
d. 進入DxeMain, 首先要Locate EFI_HII_DATABASE_PROTOCOL.
e. 再來Locate EFI_HII_CONFIG_ROUTING_PROTOCOL.
f. 把Bin[]與Strings[]與Formset GUID包成EFI_HII_PACKAGE_LIST_HEADER.
g. 利用HiiLibCreatePackageListDriverHandle產生一個Driver Handle.
h. 將產生出來的Driver Handle以及EFI_HII_PACKAGE_LIST_HEADER,
加到HII Database裡面去. 並產生一個HII Handle.
i. 安裝EFI_HII_CONFIG_ACCESS_PROTOCOL到Driver Handle裡面去.
此Protocol包含了三個Callback Function. 包含:
(1). ExtractConfig. 進入Setup Menu時會呼叫.
(2). RouteConfig. 離開Setup Menu時會呼叫.
(3). Callback. 頁面切換時會呼叫.
j. 將SCT_FORM_SET_PROTOCOL的資料填入, 並安裝給Driver Handle.
2011年6月20日 星期一
SMM Mode
SMM是CPU一個獨有的運作模式, 當CPU SMI Pin被觸發時, 就會進入到SMM Mode, 以程式而言, 它會取得Vector去看位址是多少, 而這個位址所指到的記憶體就稱為SMM RAM, 所有有關SMM的Driver都會放在這塊RAM裡面, 當產生中斷進入SMM時, 會去判斷發生中斷的人是誰, 然後去執行相關的Function, 當POST結束之後, 這塊SMM RAM就會被Lock起來, 避免Run Time時有人會去破壞.
在UEFI的架構中, SMM Driver是一個個獨立的Driver, EFI會有Dispatcher來負責執行Driver, 當執行過程中發現Driver是SMM Driver時, 這時會呼叫Kernel的Function, 將此Driver搬到SMM RAM裡面.
SMM Driver可以從Entry Point發現與DXE Driver的不同, SMM的Entry Point會先去Locate一個叫EFI_SMM_BASE_PROTOCOL Protocol, 透過此Protocol來知道目前是否在SMM Mode下, 如果不是在SMM Mode下的話, 程式會先去註冊(Register), 將這支SMM Driver的FV位址以及大小Register起來, 如此一來系統就會依照這些資訊將此SMM Driver搬到SMM RAM裡面去, 搬完之後系統會產生一次SMI, 此時會再進入一次SMM Driver的Entry Point, 第二次進入Entry Point透過EFI_SMM_BASE_PROTOCOL.InSmm ()就會知道目前是在SMM Mode下, 第二次就要透過EFI_SMM_BASE_PROTOCOL.RegisterCallback ()註冊Callback Function. 等下一次SMI觸發時, 就可以進入到Callback Function去執行.
ACPI Enable/Disable
ACPI在OS起來之後, 會去Locate DSDT Table, 在Locate之前, 會先找到FACS Table (Firmware ACPI Control Structure), FACE Table裡面有一個欄位, 會記載Software SMI的Port是多少, 以及ACPI Enable/Disable的Software SMI Number是多少, 如此一來就可以透過Out SMI_Port, ACPI_Number的方式去發SMI來執行ACPI Enable/Disable的Callback Function.
上述的動作可以參考Platform\PlatformSmm的Driver.
S3 Save
在系統進入S3之前, 有一些Chipset的內容需要儲存到記憶體內, 所以需要有一支Driver來處理這些儲存的動作, 在系統進入S3之前, 這些動作會在SMM中完成.
上述的動作可以參考Platform\PlatformS3的Driver.
要做這些儲存的動作, 會透過一種稱為"Boot Script"的命令去完成, Boot Script會在你S3回來後, 把一些已經初始化好的值回填到暫存器內, 如此一來系統才能夠S3回來之後還能夠繼續正常工作. "Boot Script"是EFI的Protocol - EFI_BOOT_SCRIPT_SAVE_PROTOCOL, 而回填的動作是在PEI完成的, 所以會透過EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI.Execute來完成.
當從S3回到OS, POST過程並不會經過DXE Driver, 但會經過PEI Driver, 所以會在PEI Driver上偵測目前的Boot Mode是否為S3, 如果是S3的話, 就透過Boot Script將值填回暫存器內.
在UEFI的架構中, SMM Driver是一個個獨立的Driver, EFI會有Dispatcher來負責執行Driver, 當執行過程中發現Driver是SMM Driver時, 這時會呼叫Kernel的Function, 將此Driver搬到SMM RAM裡面.
SMM Driver可以從Entry Point發現與DXE Driver的不同, SMM的Entry Point會先去Locate一個叫EFI_SMM_BASE_PROTOCOL Protocol, 透過此Protocol來知道目前是否在SMM Mode下, 如果不是在SMM Mode下的話, 程式會先去註冊(Register), 將這支SMM Driver的FV位址以及大小Register起來, 如此一來系統就會依照這些資訊將此SMM Driver搬到SMM RAM裡面去, 搬完之後系統會產生一次SMI, 此時會再進入一次SMM Driver的Entry Point, 第二次進入Entry Point透過EFI_SMM_BASE_PROTOCOL.InSmm ()就會知道目前是在SMM Mode下, 第二次就要透過EFI_SMM_BASE_PROTOCOL.RegisterCallback ()註冊Callback Function. 等下一次SMI觸發時, 就可以進入到Callback Function去執行.
ACPI Enable/Disable
ACPI在OS起來之後, 會去Locate DSDT Table, 在Locate之前, 會先找到FACS Table (Firmware ACPI Control Structure), FACE Table裡面有一個欄位, 會記載Software SMI的Port是多少, 以及ACPI Enable/Disable的Software SMI Number是多少, 如此一來就可以透過Out SMI_Port, ACPI_Number的方式去發SMI來執行ACPI Enable/Disable的Callback Function.
上述的動作可以參考Platform\PlatformSmm的Driver.
S3 Save
在系統進入S3之前, 有一些Chipset的內容需要儲存到記憶體內, 所以需要有一支Driver來處理這些儲存的動作, 在系統進入S3之前, 這些動作會在SMM中完成.
上述的動作可以參考Platform\PlatformS3的Driver.
要做這些儲存的動作, 會透過一種稱為"Boot Script"的命令去完成, Boot Script會在你S3回來後, 把一些已經初始化好的值回填到暫存器內, 如此一來系統才能夠S3回來之後還能夠繼續正常工作. "Boot Script"是EFI的Protocol - EFI_BOOT_SCRIPT_SAVE_PROTOCOL, 而回填的動作是在PEI完成的, 所以會透過EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI.Execute來完成.
當從S3回到OS, POST過程並不會經過DXE Driver, 但會經過PEI Driver, 所以會在PEI Driver上偵測目前的Boot Mode是否為S3, 如果是S3的話, 就透過Boot Script將值填回暫存器內.
訂閱:
文章 (Atom)