小華的部落格: 2013/9/8 - 2013/9/15

搜尋此網誌

網頁

星期五, 9月 13, 2013

簡略介紹 EDKI與EDKII (EDK2) 的差別

這篇文章主要是簡單闡述一下EDKI 與 EDKII 在BIOS工程師眼中的差別在哪裡? !
在討論之前,我們先簡單說一下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應該要寫一些。
 
希望簡略的解釋能更幫助大家在學習EDKII 甚至轉換到EDKII的時候不會驚慌失措,也比較知道為什麼要改成這樣子。




星期四, 9月 12, 2013

DosBox 模擬器 : 如何自己Compiler


        如果各位是BIOS工程師,但有時候可能有需要在 64 bit OS底下去執行Debug32.exe來看看一些組合語言的東西,但是卻發現在64 bit OS底下,Debug32.exe這隻程式是不能被執行的!

為了解決這個問題,我們通常都會去抓DosBox模擬器來使用,而這邊不是教大家去哪抓,而是跟大家說怎麼去自己抓回來Doxbox source code回來,然後使用VisualStudio 2010 自己Compiler 這個好用的工具。

首先,我們需要去抓Doxbox source code跟一些Library,而 DosBox source code 可以透過SVN抓,但是因為這個DosBox在編譯的過程中會去連結一些Library,所以就先就列出來那些會在設定環境時使用到的部分,要大家要自己先去下載:

Dosbox SVN: http://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk (我是抓Revision 3833)
 
SDL2.0:  http://www.libsdl.org/download-2.0.php  (執行DosBox.exe 需要他的SDL2.DLL)
Libpng(libpng.lib): http://www.libpng.org/pub/png/libpng.html     (我是抓1.6.3)
Zlib(zlib.lib) : http://www.zlib.net/  (我是抓Zlib 1.2.8)
WinCurses(Curses.lib): http://www.baldwin.cx/~john/projects/WinCurses.html (Debug用)

 底下是我抓下來後解壓縮放到E:\DosBox的情況:


設定DosBox Compiler環境

1.我們要先產生zlib.lib給LibPng.lib使用,所以透過VS2010 compiler的方式就是先開啟VS2010 commnd prompt,然後鍵入:
 
   E:\DosBox\zlib-1.2.8:\>  Nmake /f win32\makefile.msc
 
在編譯結束後,你會看到zlib.lib被會放在Zlib-1.2.8目錄內。


2.由於DosBox還需要連結libpng.lib,所以我們透過VS2010方案去產生libpng.lib。
   所以在開啟VS2010方案檔案前,要先把預設的ZLIB路徑指向我們前面抓的那一個zlib-1.2.8,所以先去修改zlib.props這個檔案,如下圖:
 
接著開啟方案,然後整個Rebuild Solution.
 
3.當我們需要的LIB都準備好之後,就可以開啟DOSBOX方案
 
   E:\DosBox\visualc_net\dosbox.sln
 
4. 因為我們抓的LIB版本比原本設定的還新,所以要去設定方案內的專案屬性內的C++跟Linker的設定:
 
    a. Project Properties->C++->General->Additional Include Directories -->Edit
        ../include
        ../src/platform/visualc  
        ../SDL-1.2.15/include
        ../SDL2_net-2.0.0/include
        ../lpng163
         ../zlib-1.2.8
 
   b. Project Properties->Linker->Input->Additional Dependencies-->Edit
       opengl32.lib
       winmm.lib
       ../zlib-1.2.8/zlib.lib
       ../lpng163/projects/vstudio/Debug/libpng16.lib
       ../SDL2_net-2.0.0/lib/x86/SDL2_net.lib
       ../SDL-1.2.15/lib/x86/sdl.lib
       ../SDL-1.2.15/lib/x86/sdlmain.lib
       ../curses/curses.lib
       odbc32.lib
       odbccp32.lib
       ws2_32.lib
 
5. 如果環境都設定好了,你就可以開始Rebuild,接著等一下子後你就可以看到產生DosBox.exe 到你的Release 目錄內了.
 
6. 由於產生出來的DosBox.exe 並不能單獨直接執行,還需要一些DLL跟這個執行檔放在同一個目錄內,這些DLL檔案可以從前面抓的那些LIB目錄內找的到,所以我把它集中在同一個目錄內,如下圖所示:


7. 接著你只要執行dosbox.exe (滑鼠點兩下執行)就可以看到模擬器的畫面跑出來,然後我把我自己的E Driver掛在模擬器的K drive,之後就可以在模擬器內的K:\底下找到我放在E:\Debug32.exe並且執行成功:
 
 
我的DosBox Compiler環境是在 Window8 64 bit OS,然後使用 Visual Studio 2010的 32bit compiler,所以可以看到我是選Win32 Release build,設定的目錄都是指向x86而不是x64。

 
希望這邊文章對於想要自己Compiler DosBox但是又一直不成功的人有幫助 ^^
 
 
 
 
 
 


星期三, 9月 11, 2013

一個關於INT 3h的知識分享

恩,好久沒來發文章了!  慢慢地最近比較有時間,所以會在寫些文章分享一下知識!

-----------------------------------------------------------------------------------------------------------------

一個關於INT 3h的知識分享

一般來說INT xxh的機器碼會看到是CD imm8 ,例如: CD 19 就是呼叫INT 19h.

而INT3比較特別,他有一個1 byte的OPCODE是0xCC,使用1個BYTE的好處是"他可以覆蓋在任何指令的第一個BYTE而不會去破壞掉原本的指令意思"

而2 bytes的方式就沒這個好處! 如果你了解INTEL 指令,你就會知道一行指令是由Prefix OPCODE.......部分組成的,所以一行指令所代表的機器碼長度不同,因此一個Byte的INT 3h就可以利用這些特性讓Debugger去插入INT 3h的斷點,然後跳到Debug Engine裡面.


底下是範例代碼,一個換掉原本位置的方式:

    lds      bx,BreakToAddress  ;Insert INT3h OPCODE to this addrees
    mov    al,0CCh                  ;INT 03h opcode 
    xchg   [bx],al                    ;Set INT 3h OPCODE and also save original opcode into AL          

    mov    OriginalOpCode,al   ;Save  original opcode