AMLI裡面比較常用到的指令集
AMLI(? for help)-> ?
?
Help - ? [<Cmd>]
Clear Breakpoints - bc <bp list> | *
Disable Breakpoints - bd <bp list> | *
Enable Breakpoints - be <bp list> | *
List Breakpoints - bl
Set Breakpoints - bp <MethodName> | <CodeAddr> ...
Clear Event Log - cl
Dump Event Log - dl
Dump Object Count Table - dc
Dump Heap - dh [<Addr>]
Dump Stack - ds [/v] [<Addr>]
Dump Name Space Object - dns [[/s] [<NameStr> | <Addr>]]
Dump Data Object - do <Addr>
Find NameSpace Object - find <NameSeg>
Continue Execution - g
Read Byte from Port - i <Port>
Read Word from Port - iw <Port>
Read DWord from Port - id <Port>
List All Contexts - lc
Display Nearest Method - ln [<MethodName> | <CodeAddr>]
Notify NameSpace Object - notify <Obj> <Value>
Write Byte to Port - o <Port> <Byte>
Write Word to Port - ow <Port> <Word>
Write DWord to Port - od <Port> <DWord>
Step Over AML Code - p
Quit to Kernel Debugger - q
Display Context Info. - r <Context>
Run Method - run <MethodName> | <CodeAddr> [<ArgList>]
Set Debugger Options - set [traceon | traceoff] [nesttraceon | nesttraceoff] [spewon | spewoff]
[dbgbrkon | dbgbrkoff] [lbrkon | lbrkoff] [errbrkon | errbrkoff]
[verboseon | verboseoff] [logon | logoff] [logmuton | logmutoff]
Trace Into AML Code - t
Interpreter Trace Mode - trace [trigon] [trigoff] [level=<n>]
[add=<TrigPtStr] [zap=<TrigPtList>]
Unassemble AML code - u [<MethodName> | <CodeAddr>]
AMLI(? for help)->
ACPI 裡面比較常用到的指令集
!acpicache displays all of the ACPI tables cached by the hardware application layer (HAL)
!acpiinf displays information on the configuration of the ACPI
!acpiirqarb displays the contents of the ACPI IRQ arbiter structure
!facs displays a Firmware ACPI Control Structure
!fadt displays a Fixed ACPI Description Table
!mapic displays an ACPI Multiple APIC Table
!nsobj displays an ACPI namespace object
!nstree displays a section of the ACPI namespace tree
!rsdt displays the ACPI Root System Description Table
!acpikd.help For a complete list of ACPI-related extensions.
Reference
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/acpi-debugging
將自己踏入BIOS領域中所學習到的知識做一些心得整理,像是Legacy BIOS、EFI BIOS、Windows Driver...etc. ※版權與智慧財產權聲明:保留所有法律權利。我在寫文章時如果有引用到其他人的地方我會盡量說明參考出處,如果有遺漏的地方請告訴我,我會馬上註明! 而轉貼我的文章時也請您註明出處!
星期一, 1月 15, 2018
星期三, 1月 10, 2018
如何透過DevCon.exe 去開跟關你的Device Manager內的設備
如何透過DevCon.exe 去開跟關你的Device Manager內的設備
當你安裝WDK, Visual Studio 或是Windows SDK時,這些安裝檔裡面就會包含DevCon.exe。
我的DevCon.exe是在底下這個路徑內找到的:
C:\Program Files (x86)\Windows Kits\10\Tools\x64\DevCon.exe
當然,如果你想要自己Build source code的話,你也可以從底下的路徑找到這個source code:
https://github.com/Microsoft/Windows-driver-samples/tree/master/setup/devcon
我自己也用VS2013 成功建構出來這個執行檔,只是有個小地方要注意,就是你build code之前,要用command prompt(Build environment)先執行底下的指令,先把msg.h 建立出來,不然你沒辦法用專案檔案去compiler , 因為會出現會找不到msg.h的ERROR.
C:\DevCon > mc msg.mc 會產生msg.h
底下就是一些基本的指令操作:
1)先找你要開關的Device的HWID(我是存到一個文字檔慢慢找):
devcon hwids * > D:\hwids.txt
2) 使用底下指令去disable , 記得在HW ID前面加@
devcon /r disable "@ACPI\DELL0812\3&31FF937C&0"
3) 使用底下指令去enable, 記得在HW ID前面加@,然後HWID要用" "包起來.
devcon /r enable "@ACPI\DELL0812\3&31FF937C&0"
4) 使用底下指令去重新scan hardware
devcon rescan
5) 使用底下指令可以做重新開機動作
devcon reboot
至於其他跟寫driver時會用到的指令功能,大家就看底下微軟的詳細說明囉~
Reference
https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/devcon-examples
星期二, 11月 01, 2016
ACPICA Programmer Reference Guide
隨手記錄ㄧ下AE_NOT_FOUND 出現的ㄧ些原因.
AE_NOT_FOUND : The name was not found in the namespace
AE_NOT_FOUND : A valid RSDP could not be located.
AE_NOT_FOUND : There is no table with this Signature currently loaded, or the table of the specified Instance is not loaded.
AE_NOT_FOUND : The object referenced by the combination of the Object and Pathname was not found within the namespace.
AE_NOT_FOUND: The child object parameter is the last object of the given type within the parent — a next child object was not found. If Child is NULL, this exception means that the parent object has no children.
AE_NOT_FOUND: One or more of the segments of the pathname refers to a non-existent object.
AE_NOT_FOUND: A valid ACPI table was not found at the specified Address.
AE_NOT_FOUND: An ACPI table with Signature was not found.
範例:
ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.ECDV.ECIN] (Node 008E3F28), AE_NOT_FOUND (20160930/psparse-632)
ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.ECDV._REG] (Node 008E3F70), AE_NOT_FOUND (20160930/psparse-632)
ACPI Error: Method parse/execution failed [\_SB.PCI0._INI] (Node 008D5790), AE_NOT_FOUND (20160930/psparse-632)
ACPI Error: Method parse/execution failed [\ALSD._STA] (Node 008DD4C8), AE_NOT_FOUND (20160930/psparse-632)
星期五, 2月 19, 2016
不進步就是退步
-- 以下並非以偏概全,純屬個人工作體驗 --
幾年前加入了一家日商公司,原本抱持著可以跟世界上製作第一台NB的公司裡的業界前輩學習更深入的BIOS知識,但發現事實是殘酷的,經過了多年後的改變,那邊慢慢的研發精神已經沒有那麼積極了,我不會說這家公司很糟,因為還是有很多日本/台灣/大陸/其他Region同事還是努力的在做事情,但是一家公司的文化卻讓肯做事情的人事情越做越多,不肯做事情/事情做不好的人越做越少,乃至於冗員就越來越多,聊八卦破壞團隊精神的人就多(做不好不會被裁員)。
而開發的方面,日商還是擁有許多比較封閉的開發方式,而「閉門造車」或許有其好處也有相對的壞處,而在一個世界潮流改變很快速的地方,如果不能一直學習成長,那就只能讓人超車。
因此,幾經嘗試改變周遭同事態度失敗和思考之後,我決定離開那些負面思考/消極態度的同事以及封閉的開發方式的環境,以避免個人養老心態的產生和負面心態的養成。所以在去年所以我選擇加入了另一家外商公司,開始學習不一樣領域的知識,並繼續讓自己保持正向的思考與競爭力。
然而,在這個新的工作領域中,我的工作內容暫時不需要自己去寫程式,雖然暫時放棄的寫程式的機會,但是我卻多了許多的機會去接觸不同的人事物,並讓自己反省過去到底浪費的多少生命在ㄧ些「不必要的人事物」 上面。
然而「不進步就是退步」,在最近看到ㄧ些前日商台灣同事連被詢問留下機會都沒有,就被直接裁員,最近才在找工作,心中更是感概萬千。
雖然很想幫忙,但面對到友情/現實時,我們也只能選擇性幫忙。畢竟社會是現實的,冗員與戰力你只能選擇有戰力的幫忙,否則接納到冗員的公司也只能自求多福了。
所以,在世界競爭激烈的環境之下,唯有自己持續進步,在遇到這種公司關閉/退出市場或是裁員時,我們才能在裡面繼續生存下去。
2016.02 Harrison
星期一, 2月 23, 2015
Compiler intrinsics(內建函數)
EDK2 中開/關VC++內建函數的方式
平常如果你使用Compiler /Oi 選項時,Compiler自己遇到內建函數時會自己去產生CODE到你的程式碼之中,如果你想要自己寫這些內建函數時,就必須要用/Oi- 去關閉他,以免被當成內建函數而出現Compiler error訊息。
例如,我想在我自己的xxx.c 中自己實作一個 ceil() 函數,那你可以透過EDK2 build option override方式在xxx.dsc 中來對你的xxx.inf 設定Compiler option,他只會影響你的xxx.inf。
$(MY_PATH)\xxx.inf {
<BuildOptions>
*_*_X64_CC_FLAGS = /Oi-
}
平常如果你使用Compiler /Oi 選項時,Compiler自己遇到內建函數時會自己去產生CODE到你的程式碼之中,如果你想要自己寫這些內建函數時,就必須要用/Oi- 去關閉他,以免被當成內建函數而出現Compiler error訊息。
例如,我想在我自己的xxx.c 中自己實作一個 ceil() 函數,那你可以透過EDK2 build option override方式在xxx.dsc 中來對你的xxx.inf 設定Compiler option,他只會影響你的xxx.inf。
$(MY_PATH)\xxx.inf {
<BuildOptions>
*_*_X64_CC_FLAGS = /Oi-
}
星期四, 12月 25, 2014
開啟CMD.EXE並一次執行多個DOS指令的方式(Command Prompt and Batch file)
這篇文章是分享如何開啟CMD.EXE時並一次執行多個DOS指令的方式。
為什麼要分享這個冷知識?
因為現在是冬天了,所以很冷。
好吧,我承認這是個很無聊的一篇文章,大家就將就點看吧 :)
首先呢,我們都知道Command Prompt 是執行CMD.EXE後就會產生出來的一個畫面,那我們能不能寫個批次檔去執行CMD.EXE又可以執行很多筆指令呢? 答案是可以的,做法就是寫個批次檔,然後透過"雙引號"去把所有指令包起來,指令跟指令中間加入 && 就可以了:
CMD.EXE "指令1 && 指令2 && 指令3....&&指令n"
底下就是兩個批次檔的範例,批次檔內會去執行簡單的DOS指令,執行完畢後會出現一個Command Prompt停在那邊。
TEST.bat的內容:
@ECHO OFF
CALL "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\VsDevCmd.bat"
cd/d "%1\.."
CMD.EXE
上述中的%f 是SlickEdit內的參數,%f = 目前檔案的完整路徑。
以上面的範例來說:
%f = e:\UDK2014.SP1\Nt32Pkg\Nt32Pkg
最後,我承認科技使用來自於人的惰性,不然也不會有這個冷知識可以分享,哈~
為什麼要分享這個冷知識?
因為現在是冬天了,所以很冷。
好吧,我承認這是個很無聊的一篇文章,大家就將就點看吧 :)
首先呢,我們都知道Command Prompt 是執行CMD.EXE後就會產生出來的一個畫面,那我們能不能寫個批次檔去執行CMD.EXE又可以執行很多筆指令呢? 答案是可以的,做法就是寫個批次檔,然後透過"雙引號"去把所有指令包起來,指令跟指令中間加入 && 就可以了:
CMD.EXE "指令1 && 指令2 && 指令3....&&指令n"
底下就是兩個批次檔的範例,批次檔內會去執行簡單的DOS指令,執行完畢後會出現一個Command Prompt停在那邊。
那大家可能會好奇我用在哪裡? 因為我使用SlickEdit 去編寫BIOS CODE,因為懶惰,所以想說我只要開啟 BUILD TIP底下任何一個檔案,然後按個鈕,我就可以進入到工作目錄並且設定好Visual Studio 的環境讓我可以直接Compiler code....就醬~
※ 上圖可以看到我在SlickEdit 內開啟了一個檔案,叫做NT32Pkg.dsc ,然後我設定了兩個快捷鈕,這兩個快捷鈕可以讓我選擇設定VS2012/VS2010的環境,按下去之後他會幫我呼叫設定環境的批次檔,環境設定好之後會直接幫我進入到NT32Pkg.dsc 目錄(E:\UDK2014.SP1\NT32Pkg),然後我就可以很方便地在Command Prompt內做我要做的事情了。
底下是我在那兩個快捷鍵內的設定值,有分成CMD.EXE的設定方式跟BATCH的方式,差別就只是在於呼叫CMD.EXE去做事情還是自己寫個批次檔,然後呼叫那個批次檔而已。
CMD.EXE的方式:
cmd /E:ON /V:ON /k ""C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\VsDevCmd.bat" && cd/d "%f\..""
BATCH FILE的方式(除了描述在快捷鈕之外,要多寫一個批次檔):
"C:\Apps\TEST.bat" %f
@ECHO OFF
CALL "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\VsDevCmd.bat"
cd/d "%1\.."
CMD.EXE
上述中的%f 是SlickEdit內的參數,%f = 目前檔案的完整路徑。
以上面的範例來說:
%f = e:\UDK2014.SP1\Nt32Pkg\Nt32Pkg
最後,我承認科技使用來自於人的惰性,不然也不會有這個冷知識可以分享,哈~
星期二, 12月 23, 2014
Intel® UEFI Development Kit Debugger Tool (Intel UDK Debugger and OVMFPkg)
這篇文章是紀錄我自己架設 QEMU + OVMF + Intel UDK + WinDbg 環境的筆記。
QEMU : 他是一個Open Source的處理器仿真器與模擬器。
http://wiki.qemu.org/Main_Page
OVMF : 他是一個UEFI EDK2 codebase裡面的一個專案,用來讓UEFI BIOS可以跑在虛擬機器(Virtual Machine)上面,在這裡的範例就是跑在QEMU裡面。
http://tianocore.github.io/ovmf/
Intel Uefi Development Kit Debugger Tool
下面這張圖是我實際的架設環境,我在Windows 8.1裡面安裝了Intel UDK跟WinDbg然後透過虛擬的COM Port來與 QEMU裡面的BIOS.BIN(OVMF.FD)溝通。
QEMU : 他是一個Open Source的處理器仿真器與模擬器。
http://wiki.qemu.org/Main_Page
OVMF : 他是一個UEFI EDK2 codebase裡面的一個專案,用來讓UEFI BIOS可以跑在虛擬機器(Virtual Machine)上面,在這裡的範例就是跑在QEMU裡面。
http://tianocore.github.io/ovmf/
Intel UDK Debugger : 這是INTEL開發的一個Source Level Debugger,他需要配合WinDbg(微軟提供的)才能做除錯的動作。
Intel Uefi Development Kit Debugger Tool
下面這張圖是我實際的架設環境,我在Windows 8.1裡面安裝了Intel UDK跟WinDbg然後透過虛擬的COM Port來與 QEMU裡面的BIOS.BIN(OVMF.FD)溝通。
安裝與設定(Install and Setup)
STEP1 : Download UDK2014.SP1 ,OvmfPkg and OptionRomPkg
我是把它們一起放在E:\UDK2014.SP1; 然後先準備好Compiler環境,並產生OVMF.FD. (環境的部分請參考UDK2014與OVMF的說明)。
確定Compiler 環境沒問題後,跟隨下面步驟來產生UEFI BIOS ROM。
1).先產生 OVMF.FD
a. E:\UDK2014.SP1>edksetup.bat
b. E:\UDK2014.SP1>build -DDEBUG_ON_SERIAL_PORT=TRUE -DSOURCE_DEBUG_ENABLE
2). 在把OVMF.FD複製一份,並修改檔案名稱為bios.bin (rename)
(我是放在 E:\UDK2014.SP1\Build\Ovmf3264\DEBUG_VS2012x86\FV\bios.bin)
a.E:\UDK2014.SP1> cd E:\UDK2014.SP1\Build\Ovmf3264\DEBUG_VS2012x86\FV
b.E:\UDK2014.SP1\Build\Ovmf3264\DEBUG_VS2012x86\FV> copy OVMF.FD bios.bin
b.E:\UDK2014.SP1\Build\Ovmf3264\DEBUG_VS2012x86\FV> copy OVMF.FD bios.bin
STEP2: 安裝(Install) WinDbg
STEP3: 安裝Virtual Serial Port,你可以選擇Com0Com或是VSPD(Virtual Serial Port Driver),因為Com0Com 是免費(Free),另一個要破解(VSPD v7.2),所以我這邊就只介紹Com0Com 就好,破解版的我就自己知道就好這邊就不介紹了。
1) 先執行一個Cmd.exe with Admin (管理者權限)
bcdedit -set TESTSIGNING ON
2)重新開機 (Reboot)
3) 安裝Com0Com 2.2.2.0 (For Windows 8.1/Win7 x64 bit)
4) 執行 "C:\Program Files (x86)\com0com\setupc.exe",並在畫面中輸入下面指令:
Command > Install PortName=COM6 PortName=COM7
5) 確認設備管理員(Device Manager)內有成功安裝driver,並且No yellow bang.
STEP4: 安裝(Install) Intel UDK v1.4
※如果你是Windows 8.1 ,請設定相容性=Windows 7 (Compatibility mode=Windows 7)
"C:\Program Files (x86)\Intel\Intel(R) UEFI Development Kit Debugger Tool\SoftDebugger.ini"
底下是我實作時候的設定:
COM6 = Intel UDK
COM7 = QEMU
2) 安裝後,修改SoftDebugger.ini 加入以及修改底下的描述(RED COLOR)
"C:\Program Files (x86)\Intel\Intel(R) UEFI Development Kit Debugger Tool\SoftDebugger.ini"
[Debug]
Debug=1
[Debug Port]
Channel = Serial
Port = COM6
FlowControl = 0
BaudRate = 115200
Server =
STEP5: 執行Intel UDK Debugger,他會叫出WinDbg
STEP6: 執行QEMU 並且載入UEFI BIOS (Load BIOS.bin)
E:\UDK2014.SP1\Build\Ovmf3264\DEBUG_VS2012x86\FV>"C:\Program Files\qemu\qemu-system-x86_64.exe" -L . -serial COM7
如果有不清楚的部分,可以參考INTEL相關資料。
星期五, 12月 19, 2014
VC++ 可轉散發套件(Redistributable Package)
這篇文章只是要告訴大家可轉散發套件(VC++ Redistributable Package) 是幹甚麼的?
1)首先呢,我先在我的Win7 64 bit OS底下安裝VS2008 ,安裝時順便選擇我要裝x64 compiler,這樣子我的開發環境就會有VS2008 32 bit/64 bit compiler 功能!
2) 接著,我建立一個新的VC++空專案(VC++-->General-->Empty Project),裡面加入我自己的C 語言Source code (Tmake.c 跟Tmake.h),然後再專案屬性的地方先設定Win32 (Right click Project -->Properties ,在Platform 的地方選"Win32")
3) 先產生一次32 bit的應用程式,他會產生再輸出目錄 『Debug\Tmake.exe』
4) 接著,修改專案屬性,改選擇x64 ((Right click Project -->Properties ,在Platform 的地方選"x64"),如果你沒看到x64可以選擇,就是在安裝VisualStudio時沒選擇x64 compiler選項。
5) 然後再產生一次 64 bit的應用程式,他會產生在輸出目錄『x64\Debug\Tmake.exe』
完成了步驟5之後,我就會有兩個執行檔,分別是32 bit版本跟64 bit版本。
底下是我的開發環境 (產生執行檔,但是拿到別台去執行)
OS: Windows 7 64 bit
Visual Studio 2008
底下是我的執行環境 (這台機器上面執行我自己寫的程式)
OS : Windows 8.1 64 bit
Visual Studio 2012/2013
[圖1] 32 bit/64 bit 的主要差別除了暫存器之外就是在於 Calling Convention (呼叫慣例)
所以大家可以看到,我在Win7開發拿到另一台Win8.1 上面執行,而在Win8.1中我只安裝了Visual Studio 2012/2013這兩個版本,但是我的Win7開發時是Visual Studio 2008開發的。
所以,當我在Win8.1底下不管是執行32 bit 版本的Tmake.exe 或是 64 bit 版本的Tmake.exe 我都得到了相同的錯誤訊息。
ERROR MESSAGE: 因為應用程式檔設定不正確,所以無法啟動
[圖 2] 無論32/64 bit 都得到相同的錯誤訊息
假如你看到類似這種錯誤訊息時,只要去安裝可轉發套件,把需要的檔案補足在你的電腦中理論上問題就會消失了,但是 "你要找的到正確的版本的可轉發套件" (後面會講找不到時的解決方式)。
底下版本是VS2008 version v9.0.30729
底下版本是VS2008 v9.0.30729.6161 (比上面的還新一點)
Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package MFC Security Update
另外,你可以在安裝完畢後,從System Event Log看到你到底安裝了甚麼版本:
Windows Installer 已安裝該產品。產品名稱: Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161。產品版本: 9.0.30729.6161。產品語言: 1033。製造商: Microsoft Corporation。安裝成功或錯誤狀態: 0
如果,你安裝完畢後還不能執行的話,那就是版本不同!
如果你從System Event Log 查看,也會看到類似下面的錯誤訊息:
"D:\TmakeJpg\Debug\Tmake.exe" 的啟用內容產生失敗。 找不到依存組合 Microsoft.VC90.DebugCRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"。
"D:\TmakeJpg\Debug\Tmake.exe" 的啟用內容產生失敗。 找不到依存組合 Microsoft.VC90.DebugCRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"。
意思是說你執行Tmake.exe的電腦內的所能提供的執行環境跟這個應用程式內所要求的版本不同; 從上面的範例可以知道我安裝的都是v9.0.30729.xxxx 但是這個應用程式需要的是9.0.21022.8,這個時候,你有幾個解決方式。
方式1: 從開發的機器上把需要的檔案複製到執行的機器上的Windows\System32 底下
需要的檔案需要配合你的應用程式的類型來複製對應的檔案,例如:
Release Build 64 bit(x64):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\Amd64\Microsoft.VC90.CRT
Release Build 32 bit(Win32):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
msvcm90.dll
msvcp90.dll
msvcr90.dll
Microsoft.VC90.CRT.manifest
Debug Build 64 bit(x64):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\amd64\Microsoft.VC90.DebugCRT
Debug Build 32 bit(Win32):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugCRT
msvcm90d.dll
msvcp90d.dll
msvcr90d.dll
Microsoft.VC90.DebugCRT.manifest
方式2 : 把前面這些需要的檔案打包變成xxx.exe 再一起拿去執行的電腦安裝與執行.
請參考: http://msdn.microsoft.com/en-us/library/ms235291(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/aa260978%28VS.60%29.aspx
方式3: 在專案屬性中選擇使用靜態MFC Library. (Win32/X64都要設定一次) 再重新編譯執行檔就可以了。
結論 :
VC++的轉散發套件就是給『跟你開發環境不同』的人去補足需要的Library/DLL之後,才能順利執行你所開發的應用程式。
所以,程式開發者可以選擇『自己打包好所需要的檔案』後再提供給使用者免去使用者無法執行的窘境,或是使用者自己無法執行應用程式時去安裝對應的『轉散發套件』。
[註] 我的測試程式後來採用方式3解決問題! 系統就算不安裝VC++的轉散發套件也沒問題。方式1: 從開發的機器上把需要的檔案複製到執行的機器上的Windows\System32 底下
需要的檔案需要配合你的應用程式的類型來複製對應的檔案,例如:
Release Build 64 bit(x64):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\Amd64\Microsoft.VC90.CRT
Release Build 32 bit(Win32):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
msvcm90.dll
msvcp90.dll
msvcr90.dll
Microsoft.VC90.CRT.manifest
Debug Build 64 bit(x64):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\amd64\Microsoft.VC90.DebugCRT
Debug Build 32 bit(Win32):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugCRT
msvcm90d.dll
msvcp90d.dll
msvcr90d.dll
Microsoft.VC90.DebugCRT.manifest
方式2 : 把前面這些需要的檔案打包變成xxx.exe 再一起拿去執行的電腦安裝與執行.
請參考: http://msdn.microsoft.com/en-us/library/ms235291(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/aa260978%28VS.60%29.aspx
方式3: 在專案屬性中選擇使用靜態MFC Library. (Win32/X64都要設定一次) 再重新編譯執行檔就可以了。
結論 :
VC++的轉散發套件就是給『跟你開發環境不同』的人去補足需要的Library/DLL之後,才能順利執行你所開發的應用程式。
所以,程式開發者可以選擇『自己打包好所需要的檔案』後再提供給使用者免去使用者無法執行的窘境,或是使用者自己無法執行應用程式時去安裝對應的『轉散發套件』。
星期四, 10月 23, 2014
WMI ACPI
今天要整理的筆記是WMI ACPI
在BIOS工程師中,對於WMI ACPI應該大家都有玩過,因為許多的OEM都是開發一些OS端的應用程式,然後再透過WMI 這種方式去跟BIOS的ACPI ASL CODE做溝通,以達到可以讀取Thermal 資訊/EC 資訊/ BIOS Setup Utility 資訊....etc.
在網路上或是微軟的相關文件中,你可以看到主要的架構在於wmiacpi.sys 跟acpi.sys 之間的溝通,對於BIOS工程師來說,如果要去提供這種介面就不得不參考微軟的wmi acpi白皮書上面介紹的內容了,底下是微軟文件的說明:
http://msdn.microsoft.com/en-us/library/windows/hardware/dn614028(v=vs.85).aspx
這份文件中主要的概念有幾個:
1. 他跟你說有一個MOF(Managed Object Format) 是用來給 WMI Core使用的,所以他有個資料庫管理這些MOF檔案;當上層的APP跟WMI Core溝通時,他要去這個資料庫撈對應的MOF資訊,從MOF資訊中取得一些資訊後,才知道怎麼跟你的ACPI溝通!
2.溝通的那個ACPI Device有一個特別的PNPID,也就是PNP0C14 ! 所以BIOS工程師要宣告一個ACPI Device然後底下定義_HID , "PNP0C14" 這樣子才能夠溝通~
3.Wmi Core 溝通的方式就請自行看這篇文章,像是如何透過GUID找到ACPI _WDG內比對GUID然後找到兩個字元後,再去看Flag屬性是否是Method,然後去執行相關的ACPI Method...之類的資訊,因為這些資訊已經在網路上很多,大家也應該熟悉了,這邊就不多描述。 底下是對_WDG對應時的C語言格式:
typedef struct
{
GUID guid; // GUID that names data block
union
{
CHAR ObjectId[2]; // 2-character ACPI ID (Data Blocks and Methods)
struct
{
UCHAR NotificationValue; // Byte value passed by event handler control method
UCHAR Reserved[1];
} NotifyId;
}
USHORT InstanceCount; // Number of separate instances of data block
USHORT Flags; // Flags
};
上面的C結構會對應倒ASL的_WDG 內的定義:
Name(_WDG, Buffer() {
0x6a, 0x0f, 0xBC,....//GUID
66, 65, // Object ID (BA) (兩個字元"BA",可能會組成WQBA或是WMBA,看Flag)
3, // Instance Count (有幾筆Data items)
0x01, // Flags (決定他是不是Method...之類的屬性來決定WQXX/WMXX...etc)
})
那大家可能會問說,你不說運作原理那你要說甚麼?
一般BIOS工程師在Debug時一般就是利用這些運作原理去追ACPI 來找出問題點,一般大家會比較忽略說,那上層的MOF是怎麼加進去資料庫的? 所以這邊會對這部分做一個簡單的說明。在說明之前,我們先看看下面這張圖:
Vbscript : 代表的就是上層APP可以透過像是VBScript/C#....etc之類的去開發你的APP。
Wmi Core : 會去撈MOF 資訊跟Acpi.sys溝通(透過WmiAcpi.sys) 。
ACPI ASL : 你要宣告PNP0C14 ,然後有個Name Object 叫做 _WDG (上面圖畫錯了,懶得改了)。
BIOS Function: 然後透過ACPI ASL的相關Method來實做一些BIOS CODE,像是發個SMI去取得一些資訊,再透過WMI_ACPI ASL往回傳給上層APP...etc.。
Wmi Core : 會去撈MOF 資訊跟Acpi.sys溝通(透過WmiAcpi.sys) 。
ACPI ASL : 你要宣告PNP0C14 ,然後有個Name Object 叫做 _WDG (上面圖畫錯了,懶得改了)。
BIOS Function: 然後透過ACPI ASL的相關Method來實做一些BIOS CODE,像是發個SMI去取得一些資訊,再透過WMI_ACPI ASL往回傳給上層APP...etc.。
Installation wmi acpi方式有兩種:
方式1: MOF包在DLL,並註冊到Registry
1. 增加上述說的那些ASL CODE到你的BIOS
2. 建立一個MOF.DLL (類似OS動態連結檔,不過裡面沒有任何OBJ只有MOF資料)
a. 建立wmiacpi.rc 跟wmiacpi.def 檔案
a. 建立wmiacpi.rc 跟wmiacpi.def 檔案
b. 透過VS2010/2012/2013 的link.exe 將他變成wmiacpi.dll 裡面沒有obj,只有 MOF資料
wmiacpi.rc 內容:
#include <ntverp.h>
#define VER_FILETYPE VFT_DLL
#define VER_FILESUBTYPE VFT_UNKNOWN
#define VER_FILEDESCRIPTION_STR "Resource only DLL containing MOF for ASL code"
#define VER_INTERNALNAME_STR "wmimof"
#define VER_ORIGINALFILENAME_STR "wmimof.DLL"
#include "common.ver"
//
// WMIACPI.SYS requires that the mof resource be named MofResource
MofResource MOFDATA wmiacpi.bmf
wmiacpi.def 的內容就只有一行:
LIBRARY wmiacpi.dll
c. link command :
link /OUT:"%OUTDIR%\wmiacpi.dll" /NOLOGO /DLL "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib"
"ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /DEF:"wmiacpi.def" %OUTDIR%\wmiacpi.res /MANIFEST /ManifestFile:"%OUTDIR%
\wmiacpi.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /PDB:"%OUTDIR%\wmiacpi.pdb" /TLBID:1 /NOENTRY /DYNAMICBASE
/NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
3. 複製MOF.DLL檔案到%windir%\system32 (也就是C:\Windows\System32)
4. 在Registry 的HKEY_LOCAL_MACHINE\CurrentControlSet\Services\WmiAcpi底下新增MofImagePath,然後裡面的值指向 "C:\Windows\System32\MOF.DLL"
5. 重新開機,然後OS偵測到PNP0C14之後就會自動安裝WmiAcpi.sys 然後會去Registry 找到你包在MOF.DLL內的資料,之後用你的APP來透過WMI Core去存取你的ACPI ASL.
※ 這邊說的MOF.DLL就是你透過link.exe 建立出來的檔案,請自行變更你的名稱
方式2: MOF包在ACPI ASL,等發送特定IRP時回給Wmi Core.
1. 增加上述說的那些ASL CODE到你的BIOS
2. 建立一個MOF.BMF (MOF的Binary格式,副檔名隨便給因為你可以在Compiler時指定副檔名)
3. 透過 wmimofck.exe 產生.x 檔案,在把他的內容包到ACPI ASL之中.
a. 首先先在_WDG內定義一個專屬MOF的GUID(切記不能改變GUID值)
Name(_WDG, Buffer() {
.
// This GUID for returning the MOF data
0x21, 0x12, 0x90, 0x05, 0x66, 0xd5, 0xd1, 0x11, 0xb2, 0xf0, 0x00, 0xa0, 0xc9, 0x06, 0x29, 0x10, //
66, 65, // Object ID (BA) 這兩個字元可以自己改,但是要對應到WQXX.
1, // Instance Count
0x00, // Flags
})
b.將Wmiacpi.x 內容複製貼上到Name Object "WQBA"
Name(WQBA), Buffer(){"MOF Binary data from Wmiacpi.x"}
4. 重新開機,然後OS偵測到PNP0C14之後就會自動安裝WmiAcpi.sys 然後會發送特定的IRP,然後ACPI那邊會回給WMI CORE MOF的資訊~
在這兩中方式中,都需要把wmiacpi.mof 檔案先經過一個工具叫做mofcomp.exe compiler
而這個wmiacpi.mof 檔案的內容就是你在微軟文件那邊看到的,例如:
class WMIEvent : __ExtrinsicEvent
{
};
[WMI,
Locale("MS\\0x409"),
Description("This class contains the definition of the package used in other classes"),
guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")
]
class Package
{
[WmiDataId(1),
read, write,
Description("16 bytes of data")
] uint8 Bytes[16];
};
...
然後經過mofcomp.exe compiler之後,會產生一個MOF binary 檔案,我把他叫做wmiacpi.bmf。
而這個wmiacpi.bmf 可以經過另一個工具wmimofck.exe 來產生c file / c header file ,如果你想自己寫一個Wmi driver時,可以透過這種方式把來幫助你產生一些需要的程式碼,也可以透過wmimofck.exe來產生VBScript 的Sample code(自動產生),所以當然也可以透過wmimofck.exe來產生一堆HEX 文字檔來方便你把MOF binary資料包進去ACPI ASL之中。
底下是我的批次檔,用來測試用的,分享給大家參考~
※ 這邊使用到的資訊都是來自於微軟的相關文件,有興趣請自行查詢!
需要用到的工具:
Windows WDK內的wmimofchk.exe (我是安裝WDK for win7 ,目前最新版是WDK 8.1)
Reference
http://msdn.microsoft.com/en-us/library/windows/hardware/dn614028(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/hardware/ff542012(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/hardware/ff554794(v=vs.85).aspx
星期二, 9月 16, 2014
EDK2/EDKII Python Build Tool 兩三事 (Build.py)
EDK2 Python Build Tool 兩三事
最近因為工作需要,所以不得已逼自己去把EDK2 Python Build source code看完,看完後順便整理一下一些小重點,以免過陣子自己又忘記了。
1)EDK_GLOBAL
這種定義的Macro只能給EDK1 driver使用,因為他會去檢查.inf 內的
INF_VERSION = 0x00010005 ,如果大於或是等於這個值就是當成EDK2,如果找不到這個值就會當成是EDK1。
因為不好用,所以就隨手改了一下CODE,讓他通吃EDK1 + EDK2 + FDF + DSC + DEC + INF
2) Build Rule and Package rule
在EDK2 中,他把EDK1原本的Build Rule & Package Rule 分別描述成:
Tools_def.txt
Build_Rule.txt
[Rule.$(Arch).$(ModuleType]
好不好用看個人,不過如果你要支援原本EDK1 Package Rule時那就對不起啦,你要修改Python source code,不然你做不到。 例如說底下的EDK1 的COMPONENT_TYPE = FILE原本對應到某個Package Rule,但是在EDK2內不支援就是不支援,除非自己改python source code.
BASE_NAME = xxxxx
FILE_GUID = 126A4D6A-C404-4200-8779-F327A4A79087
COMPONENT_TYPE = FILE
BUILD_TYPE = MAKEFILE
3) Python v.s SQL
Python build tool 只是拿SQL當成是存放他收集到的資料的一個地方,然後在另一個地方就可以去撈資料庫內的資訊然後寫對應的CODE去分析要幹嘛,所以rebuild的時候最好把這個資料庫暫存檔案刪除。 EX: Conf\.cache\build.db
4) GenSection & GenFFS
以前EDK1的這兩個工具也整合進去Python Build tool內了,所以想了解FDF是怎麼產生FV或是FD的人就請自行研究,不過他是另一隻Tool叫做GenFds.py。
5) AutoGen.c v.s AutoGen.h
偷偷產生的檔案用來存放一些PCD操作/有用到的PCD Value,GUID 定義跟一些偷塞的include... 如果是給PCD database使用的,他還會塞Dynamic PCD給PCD 資料庫當成初始化值。
另外,Library 只會產生AutoGen.h 不會產生AutoGen.c,因為Library通常會跟某個Driver Link,所以等到真正要去產生Module make時,才會去檢查Library 內用到的GUID/PCD ,然後產生在Module's AutoGen.c內。
6) Hard code
恩,很多東西都寫死在Python build tool內,像是nmake command 要增加修改時就要改一改他,不過也是個好處,就是我可以偷加很多東西在裡面,然後不給你source code...哈!!!
7) 產生執行檔
.py 轉成 .exe 方式我自己再用的有兩種,一種是py2Exe不過版本過舊已經不能支援了,所以我採用EDK2 所建議的cx_Freeze 去轉換,轉換時還要搭配你的Python 版本,目前我看到的codebase內使用的是Python 2.7.3,所以應該以這個為主吧! 底下是EDK2 建議的方式:
Using cx_Freeze 4.2.3 with Python 2.7.2
Using cx_Freeze 3.0.3 with Python 2.5.4
8) 嗯...有想到再說~
星期三, 2月 12, 2014
Python v.s UEFI EDK2 (EDKII)
這篇文章主要是幫自己紀錄一下學習EDK2 build process時的前置準備動作有哪些,後面會陸陸續續把這篇文章補齊,所以先留下個紀錄吧~
學習方式
對於EDK2來說最大的轉變就是我一直提到的Build process,我常跟我周遭朋友說如果你要學好BIOS或是其他大型軟體專案,中間的『眉角』就是要把大型專案的學習方式分成:
BUILD + CODE
當你有辦法分辨以及分開學習時,你才可以精準的掌握住甚麼是BUILD? 甚麼是CODE?
舉例來說,BUILD的部分就是屬於build rule/compiler rule/package rule ,簡單的說就是透過一些方式來把程式碼產生成binary,依照一些特定的layout來產生成一個BIOS ROM image;至於CODE的部分就屬於程式語言,像是C語言,組合語言的學習! 你唯有了解彼此之間的關係,你才能掌握關鍵處! 這也是我常跟朋友開玩笑說,你真的會"build+code"嗎?!
至於BUILD PROCESS的概念中,我也常常教導朋友去思考為什麼要這樣子做? 他解決了甚麼問題? 有沒有其他方式? 因此我常常由一個批次檔的概念外加一些淺而易懂的範例來讓他們知道說原來BUILD PROCESS原理是如此簡單,不過我沒打算在這邊寫詳細的解說,因為配合著畫圖邊解釋效果比較佳,如果大家有興趣又剛好在業界遇到我時再來跟我討論吧! ^^
所以記得,學習的方式就是BUILD + CODE分開來學!!!
前置動作
有鑑於EDK2 BUILD PROCESS主要的部分已經改成Python 2.5/2.7開發,美其名是為了跨平台而準備,但是實際上卻沒有達成! 畢竟,EDK2在x86中並沒有拿Python 將所有win32 的工具重新寫一次,導致在x86平台中有一部分的python tool跟一部份的win32 tool,所以只能說『某些BUILD TOOLS』跨平台而已! 但是木已成舟,所以現在的x86上就變成了這個怪胎情況了!
雖然我不討厭Python,但也不是擁護者,因為跨平台方式有很多種,他也不是最好的一種! 但是因為EDK2都選擇了Python,所以我也要強迫自己來學習他,秉持著工欲善其事,必先利其器的方式,我們先把除錯工具安裝好,以方便我們去分析與研究EDK2's Build.py
那有哪些東西要先安裝呢? 我個人偏好Visual Studio,因此我選擇了VS2010+PTVS 來當作是Debugger,安裝簡單! 當然你也可以選擇使用Eclipse Classic IDE + PyDev 的除錯方式 (感謝鳥公司John大大傾囊教學)!
所以如果你也想學Python,請跟著我一起安裝:
1. VS2010
2. Python tool for Visual Studio
https://pytools.codeplex.com/
3. Python 2.7.6 (目前EDK2還沒支援到Python 3.x,建議是安裝2.5.x/2.7.x)
http://www.python.org/download/releases/2.7.6/
Eclipse Classic IDE+PyDev
VS2010+PTVS
(未完待續...)
學習方式
對於EDK2來說最大的轉變就是我一直提到的Build process,我常跟我周遭朋友說如果你要學好BIOS或是其他大型軟體專案,中間的『眉角』就是要把大型專案的學習方式分成:
BUILD + CODE
當你有辦法分辨以及分開學習時,你才可以精準的掌握住甚麼是BUILD? 甚麼是CODE?
舉例來說,BUILD的部分就是屬於build rule/compiler rule/package rule ,簡單的說就是透過一些方式來把程式碼產生成binary,依照一些特定的layout來產生成一個BIOS ROM image;至於CODE的部分就屬於程式語言,像是C語言,組合語言的學習! 你唯有了解彼此之間的關係,你才能掌握關鍵處! 這也是我常跟朋友開玩笑說,你真的會"build+code"嗎?!
至於BUILD PROCESS的概念中,我也常常教導朋友去思考為什麼要這樣子做? 他解決了甚麼問題? 有沒有其他方式? 因此我常常由一個批次檔的概念外加一些淺而易懂的範例來讓他們知道說原來BUILD PROCESS原理是如此簡單,不過我沒打算在這邊寫詳細的解說,因為配合著畫圖邊解釋效果比較佳,如果大家有興趣又剛好在業界遇到我時再來跟我討論吧! ^^
所以記得,學習的方式就是BUILD + CODE分開來學!!!
前置動作
有鑑於EDK2 BUILD PROCESS主要的部分已經改成Python 2.5/2.7開發,美其名是為了跨平台而準備,但是實際上卻沒有達成! 畢竟,EDK2在x86中並沒有拿Python 將所有win32 的工具重新寫一次,導致在x86平台中有一部分的python tool跟一部份的win32 tool,所以只能說『某些BUILD TOOLS』跨平台而已! 但是木已成舟,所以現在的x86上就變成了這個怪胎情況了!
雖然我不討厭Python,但也不是擁護者,因為跨平台方式有很多種,他也不是最好的一種! 但是因為EDK2都選擇了Python,所以我也要強迫自己來學習他,秉持著工欲善其事,必先利其器的方式,我們先把除錯工具安裝好,以方便我們去分析與研究EDK2's Build.py
那有哪些東西要先安裝呢? 我個人偏好Visual Studio,因此我選擇了VS2010+PTVS 來當作是Debugger,安裝簡單! 當然你也可以選擇使用Eclipse Classic IDE + PyDev 的除錯方式 (感謝鳥公司John大大傾囊教學)!
所以如果你也想學Python,請跟著我一起安裝:
1. VS2010
2. Python tool for Visual Studio
https://pytools.codeplex.com/
3. Python 2.7.6 (目前EDK2還沒支援到Python 3.x,建議是安裝2.5.x/2.7.x)
http://www.python.org/download/releases/2.7.6/
Eclipse Classic IDE+PyDev
VS2010+PTVS
(未完待續...)
標籤:
EFI BIOS相關知識
星期二, 1月 21, 2014
文字檔格式真多,那怎麼去區別ASCII/Big5/UTF-16/UTF-8呢?
以前處理一些字幕檔的時候,慢慢的累積了一些區別文字檔編碼的經驗,這邊就分享一下個人經驗,不過經驗歸經驗不一定正確,所以各位就將就點看,把他當成是解決你問題的一個進入點,然後再去搜尋相關知識來解決各位遇到的問題吧!
首先,我們先討論一下文字檔到底是啥? 其實不管是甚麼檔案,儲存的時候都是BINARY資料,差別就在於讀取檔案的人想要如何呈現給你看而已~
例如:
執行檔=二進制資料 , OS 讀取表頭判定他可以被執行,然後執行他!
文字檔=二進制資料 , Editor 讀取他然後依照一些編碼原則判定他,然後再去字型檔撈出字型顯示給你看!
所以啦,這篇文章要說的就是模擬一下如果我寫了一個Editor,我要怎麼區別不同的編碼格式!
從上面的圖中可以看到,一開始的時候我會先去讀取兩個位元組,這是因為Unicode(UTF-16)檔案會有一個標記來標記他是Unicode存取方式是Big Endian還是Little Endian (低位元組在記憶體低位址, x86常用) ,所以大家可以把UEFI 中的.uni 用16進制編輯器打開來看看,就會看到檔案最開頭有這個標記可以用來判斷~
如果沒有這個標記的檔案,我們就可以判斷為他可能是ASCII/UTF-8/Big-5的編碼方式,因為Big5是兩個位元組組成,他有他一定的規範,所以可以由這些規範來判別字元是不是Big5或只是單純ASCII的一個位元組而已~
除此之外,還有一個UTF-8比較討厭,因為UTF-16是固定兩個位元組儲存一個字元,所以像是英文"A"就會是0x0041 ,高位元組永遠是0x00,所以為了節省空間所以變成了可變位元組的編碼,因此一個字元可能由1~6 bytes組成,看樣子還有機會繼續延伸咧~
因此可以參考Wiki上的UTF-8的對應方式去判讀一個字元由幾個Bytes組成。
例如: 中文字 [這]
這=E9 80 99 (UTF-8)
第一個位元組的二進制是1110 1001前面的'1'代表全部是3 bytes,而後面的每個位元組的bit7:6就是對應Wiki上說的欄位表示 10xx xxxx, 10xx,xxxx
所以取出來的xxxx xxxxxx xxxxxx
| | |____ 011001 19
| |____________ 000000 0
|_________________ 1001 9
U+9019 就是unicode的中文字 [這],所以UTF-8 也算是再重新編碼後的一種unicode表示碼!
不知道舉的這些例子看倌們能否了解?!
因為這不是我的專長,我是寫BIOS的,以上是經驗談~ Orz
星期二, 1月 07, 2014
UEFI Gop driver and PlatformGopPolicy
最近在除錯我自己從無到有DIY出來的EDKI codebase的問題,所以在這邊留一下筆記來記錄一下UEFI Gop driver遇到的問題~
問題描述:
由於我們的系統比較特別,有eDP Panel 跟LVDS Panel(銷庫存),所以外掛了一顆eDP-LVDS IC,導致點亮VGA的方式變得複雜了點,另外我的CODEBASE目前還很陽春,所以只支援UEFI mode,也就是我要直接上UEFI GopDriver,而執行到UEFI Gop Driver後系統就當機了,為了這個問題所以把這隻Gop driver 反組譯,然後大致追了一下,然後把追CODE的筆記紀錄在下面!
筆記:
1) 他是一個EFI driver model driver,所以從DriverBinding Start()追進去看他做了甚麼事情
2) 底下是我整理的資料,因為沒有他的Source code,完全靠反組譯去猜測出底下的順序與動作,所以僅供參考,並不一定正確!
3)Root cause: 還不清楚,還在追...哈!
b.Undocument protocol (39487C79-236D-4666-87E5-09547CAAE1BC) : 不知道是幹嘛的...
c.EdidDiscovered (1C0C34F6-D380-41FA-A049-8AD06C1A66AA): 用來表示於顯示設備使用這個EDID.
d.GraphicOutput(9042A9DE-23DC-4A38-96FB-7ADED080516A):用來顯示影像
e.EdidActiveProtocol(BD8C1056-9F36-44EC-92A8-A6337F817986) : 正在顯示的設備使用這個EDID
如果SizeOfEdid !=0 代表EDID資料應該是有效的,應該可以檢查此Handle上面有沒有EDID Protocol來得到顯示設備的EDID,就像是Legacy 時呼叫INT 10h.
問題描述:
由於我們的系統比較特別,有eDP Panel 跟LVDS Panel(銷庫存),所以外掛了一顆eDP-LVDS IC,導致點亮VGA的方式變得複雜了點,另外我的CODEBASE目前還很陽春,所以只支援UEFI mode,也就是我要直接上UEFI GopDriver,而執行到UEFI Gop Driver後系統就當機了,為了這個問題所以把這隻Gop driver 反組譯,然後大致追了一下,然後把追CODE的筆記紀錄在下面!
筆記:
1) 他是一個EFI driver model driver,所以從DriverBinding Start()追進去看他做了甚麼事情
2) 底下是我整理的資料,因為沒有他的Source code,完全靠反組譯去猜測出底下的順序與動作,所以僅供參考,並不一定正確!
3)Root cause: 還不清楚,還在追...哈!
DriverBinding->Start()
{
1..asm{RDTSC};
2.ProgramIGD();
a. OpenProtocol(Pciio) //準備用來讀取PCI Regs
b. Pciio->Attributes(Enable BusMatser,MMIO,IOBASE) //啟動IGD設備
c. OpenProtocol(DevicePath)
d.LocateProtocol (PlatformGopPolicy) //要求Platform firmware(也就是BIOS)提供VBT/Lid/Dock 的資訊
e. PlatformGopPolicy->GetVbt(Address,Size);
f. Config/Read IGD PCI Regs (DeviceId,RevisionId...etc)
g.Read Pch DeviceId and RevisionId.
h.Init MMIO regs // 目前還找不到相關文件說明這些暫存器在幹嘛
i.Out 0x3c2,0x67
j.Config MMIO regs
k. PlatformGopPolicy->PlatformLidStatus()
l. PlatformGopPolicy->PlatformDockStatus() if PlatformGopPolicy's revision > 0x0001 otherwise, ignore it.
m.Create DDEV LinkedList (Display Device) //應該是參考Vbt去建立出來的資訊 CRT->eDP->EFP1->EFP2->EFP3
n.Walk DDEV LinkedList to find out predefined DDEV and then try to enable it. (Hangup here.) //我當機在這裡
o.Others //還沒追...應該是去產生一些protocol (EDID,brightness...etc) 或是devicepath
3.asm{RDTSC};
}
4)會被產生出來的Protocol掛自Child Handle上:
a.DevicePath (09576E91-6D3F-11D2-8E39-00A0C969723B)b.Undocument protocol (39487C79-236D-4666-87E5-09547CAAE1BC) : 不知道是幹嘛的...
c.EdidDiscovered (1C0C34F6-D380-41FA-A049-8AD06C1A66AA): 用來表示於顯示設備使用這個EDID.
d.GraphicOutput(9042A9DE-23DC-4A38-96FB-7ADED080516A):用來顯示影像
e.EdidActiveProtocol(BD8C1056-9F36-44EC-92A8-A6337F817986) : 正在顯示的設備使用這個EDID
如果SizeOfEdid !=0 代表EDID資料應該是有效的,應該可以檢查此Handle上面有沒有EDID Protocol來得到顯示設備的EDID,就像是Legacy 時呼叫INT 10h.
星期五, 9月 13, 2013
簡略介紹 EDKI與EDKII (EDK2) 的差別
這篇文章主要是簡單闡述一下EDKI 與 EDKII 在BIOS工程師眼中的差別在哪裡? !
在討論之前,我們先簡單說一下Package是甚麼東西?
希望簡略的解釋能更幫助大家在學習EDKII 甚至轉換到EDKII的時候不會驚慌失措,也比較知道為什麼要改成這樣子。
在討論之前,我們先簡單說一下Package是甚麼東西?
Package是甚麼?
在EDKI裡面,我們在寫UEFI driver的時候並不會有所謂的 "Module" 的概念在裡面。我們開發的時候都是以 driver為單位,並不會考慮一些模組化的問題。
[註] UEFI 的可執行檔案我們的術語是Image或是Driver,所以當你聽到這個術語時把他當成類似EXE執行檔就可以了。
而 EDKII裡面,他加上了 Package這個概念(模組化)。其實可以把它看成是一個目錄,而這個目錄名稱會是"xxxPkg",而目錄裡面就是一堆相關的UEFI driver。
所謂的相關的UEFI Driver是說,假如你看到目錄名稱是"NetworkPkg",那麼這個Package裡面的東西就跟Network有關,所以在這個目錄內可以有其他子目錄去存放著 PEI/DXE/SMM/APP 的 Driver或是 Library。
而組成一個 Package的元素(一個PKG目錄內)必定包含一個 *.dec 和 *.dsc
Package的好處是甚麼? 就是"獨立"
在EDKI 的時候,你想單獨產生一個特定的CODE時,你至少"整套CODE"要先產生一次! 而EDKII使用這種"獨立"的概念就不需要整套CODE build完才產生你要的CODE!
但也是因為獨立,所以有很多地方都是為了解決獨立出來問題而去改了一堆Build tool動作跟你描述.dsc還有.FDF的動作。
EDKI與EDKII主要的差別?
- Build process的改變
EDKI : 由ProcessDsc.exe執行將 *.inf 轉換成 makefile 的動作
EDKII: 由Build.py 去處理,同時還會產生 AutoGen.c & AutoGen.h (Parsing *.dec )
- DSC file / FDF file
在EDKI裡,決定一個 driver要放在那一個 firmware volume裡是在"1個.dsc"就可以決定的,通常都會是叫做PlatformDsc.dsc或是 Build.dsc這個檔案!
在檔案內你會透過FV=FVREVOVERY的方式把底下的UEFI Driver通通放進去FVREVOVERY.FV,接著透過Flashmap.fdf去規劃ROM的區域,然後決定 FVMAIN.FV放進去哪個區域。
但是 EDKII為了實現 Package這個概念,所以.dsc不再用來描述UEFI driver要放到哪個FV,而只是拿來決定要不要BUILD這目錄下的UEFI driver而已!
描述那些UEFI DRIVER放到ROM的哪個位置的動作就變成EDKII新的FDF SPEC所描述的那些動作,所以你必須要新的FDF 格式中描述你那些UEFI driver是要放進去ROM裡面的。
- PCD/DEC
因為EDKII還希望做到不用改到Source code就能夠改變CODE的行為,所以延伸出了PCD這種控制方式,不過我是覺得它需要額外寫TOOL去達到他的理念而增加了許多BIOS工程師的麻煩。
PCD我自己是分成兩部分學習,一部分是屬於如何在RUNTIME管理PCD Database的部分,另一部分就是如何透過DEC FILE去產生PCD的預設值以及有哪些PCD LIB與Header file可以存取他,因為這部分牽扯到實作面(靠的是C語言巨集),所以需要邊開著CODE邊解釋,所以很難使用文章解釋,希望大家有機會在業界遇到我時在幫大家解釋吧^^.
你暫時可以簡單把他想像成是一個變數宣告的方式,變數會有生命週期(整個RUNTIME或是某一個DRIVER而已)與屬性(唯讀/可讀寫),可以方便你在CODE裡面存取他!
以上的部分大致上就是EDKI 與EDKII的差別,對於BIOS工程師來說可能會需要去習慣新的DSC/INF/DEC/FDF寫法,以及BUILD.py這個工具的用法,其他的就是要去習慣各家IBV對於PCD的作法!
EDKI與EDKII Reference Code的差別?
EDKI 與 EDKII Reference code的部分,以目前我接觸到的部分來說最大的差別在於"移植的觀念"。
EDKI 身不好移植到不同平台,所以EDKII在這部分是希望能夠好移植,而他的使用的方式是約束大家使用同一個EntryPoint,也就是說在EDKII RC code部分,如果大家的EntryPoint都能指向同一個地方做完一些跟Platform相關的事情之後再跳回去Driver EntryPont,那麼下次如果要移植到不同平台時,我只要把這個共通的EntryPoint改寫就好了。
所以在 RC CODE部分,你會看到他先透過共同的_ModuleEntryPoint,然後再從C_FLAG設定的給EDKII Gule Library的EntryPoint 跳回去你設定的Driver EntryPoint,這就是他主要的改變!
因為EDKII Glue Library做掉一些事情了,所以以前在UEFI Driver內可能一開始會去呼叫InitDxeLib()來初始化gBS/gRT/gST的動作就不用做了,另外Smm Driver寫法也略有不同,其實都是因為被偷做,所以你可以少做!
EDKI與EDKII Code Size的差別?
由於EDKI 本身在LIBRARY撰寫部分並沒有明確規範,所以連結出來的可執行檔的CODE SIZE會比較大,在EDKII上也針對了這部分重新改寫了原來的LIBRARY以減少連結時的CODE SIZE,因此理論上EDKII 環境下產生出來的可執行檔SIZE應該要寫一些。
標籤:
EFI BIOS相關知識
訂閱:
文章 (Atom)














