本文主要分為如下幾個部分:
1、 EFI Overview :主要從整體上去描述一下什么是EFI。以及應用EFI對我們可能帶來的好處。
2、 Framework : 從原理,架搆等幾個方面重點介紹了EFI規範的一種標准實現Intel Platform Innovation Framework for EFI(以下簡稱Framework)。
3、 Development Tools :重點介紹了目前由AMI提供的開發工具Visual eBIOS。并簡單探討了Insyde公司的相關工具。 同時還介紹了American Arium公司提供的硬件仿真器以及調試軟件Source Point。
4、 EFI Development : Applications & Drivers :詳細探討了EFI開發的一些細節問題。并分析了一個簡單的EFI Applications。同時還探討了EFI Drivers。
5、 EFI Shell :探討了EFI Shell。
以上是主要的幾個討論方向,具體還會細分,詳見正文部分。
1、EFI Overview EFI綜述
1.1 Problems on legacy BIOS 傳統BIOS所面臨的難題
在仔細的探討EFI之前,我們先來回顧一下什么是BIOS。BIOS是英文Basic Input/Output System的縮寫,意為基本輸入輸出系統。從IBM於上世紀八十年代初推出了全世界第一台PC機開始,BIOS就成了個人計算機必備的系統軟件,用於管理基本的硬件,提供各種中斷調用,引導操作系統等等。可以看出,BIOS對於個人計算機來說,是非常重要的系統軟件,沒有BIOS的計算機是無法運行的。
傳統上的BIOS經過了長達20多年的時間,基本上沒有大的特別的改進,在操作系統已經完全32位化的今天,BIOS仍然停留在16位實模式時代。我們知道,在這個模式下,IA32架搆的CPU只能訪問1MB的基本內存,這就大大的***了程序員的創造性。同時,各種板卡上的BIOS在映射到系統內存中的時候,受到128Kbytes的大小***。這使得一台計算機不能安裝太多的板卡,否則他們的BIOS的容量將很容易突破128Kbytes,但是在一些服務器上,安裝很多板卡已經很常見。
同時由於BIOS一般選擇釆用匯編語言直接開發,使得開發入門難度很大。很多初級工程師甚至無法完成這樣的任務。并且各個公司之間的代碼不兼容,嚴重阻礙了其發展。
1.2 Intel’s solutions :EFI Intel的解決方案:EFI
EFI是Intel為了解決上述的BIOS難題而推出一項新技術,旨在向業界提供一種在未來20年內仍然可以應用的BIOS架搆。EFI是Extensible Firmware Inte***ce的縮寫。中文意思是可擴展固件接口。由於目前習慣上叫做EFI,本文將繼續稱其為EFI而不是它的中文譯名。
正如它的名字一樣,EFI并不是一套軟件,而是一整套定義的很好的接口。它是一種規範,Intel目前已經正式發布了EFI Specification Revisions 1.10。任何人都可以按照EFI寫出自己的實現來。而Intel也為我們准備好了一個標准的實現:Intel Platform Innovation Framework for EFI(以下簡稱Framework)。更加值得一提的是,Framework在BSD協議的規範下,已經實現了開放源代碼,這為我們今後開發在EFI之上的應用提供了充分的技術保障。
1.3 Benefits of the EFI EFI的優點
EFI設計的充分原則就是屏蔽掉下層的硬件,事實上通過我們的分析,EFI已經很有操作系統的味道,EFI大概包括如下的幾個部分:
1) Pre-EFI基礎代碼
2) 針對特定晶片的Pre-EFI模塊
3) DXE基礎代碼
4) DXE驅動(Framework)
5) DXE驅動(硬件)
6) 兼容性支持模塊CSM(可選,只支持IA32)
EFI通過上述的這些組成部分,提供了以往BIOS可以提供的全部功能,并且做了大量的更新。同時在容量上也做的相當的完美,可以放入4MB的Flash中。而啟動速度和喚醒速度也符合HDG標准。
更加重要的是,EFI要求使用C語言作為開發語言,這樣一來,使得我們可以更加容易的加入到BIOS的開發中來,同時也容易實現模塊化與標准化。完全模塊化的一個好處就是那些ODM或者OEM們可以方便添加他們想要的功能到EFI上。對我們而言,好處也是不言自明的,如果我們決定開始基於EFI的項目,那么我們可以在EFI中添加屬於我們自己的模塊,更加方便我們的用戶的定制,甚至為用戶提供個性化服務提供了可能。
1.4 Supported OS 操作系統系統支持情況
目前正式宣布支持EFI的操作系統包括Microsoft Windows Longhorn以及部分Linux。目前Longhorn已經進入了Beta1測試階段,Intel也在一個DEMO中展示了用EFI來引導Longhorn的實際情況。同時展示的還有如何用EFI去引導RedHat Linux(需要借助一個第三方的開源軟件ELILO)。至於其他的操作系統如Windows XP等,則暫時還不能支持EFI,所以只得使用CSM來達到引導目的。
2、 Framework
2.1 Framework Overview 架搆綜述
簡單的說,Framework就是EFI的一種實現,由Intel完成。完全實現了EFI Specification Revisions 1.10中提及的各項功能。開發者可以基於Framework,開發出各種EFI應用來。同時也可以為Framework新增新的功能。
2.2 Benefits of using the Framework 使用Framework的好處
最大的好處可以大大減輕我們的勞動量,我們只把注意力集中到最需要注意的地方上去,既然已經有了EFI的實現,并且是開源的實現,那么自然不需要我們再次實現一次。此外,Framework的其他一些好處還包括:
(1)跨平台Cross platform 目前Framework可以支持Intel IA32/64,XScale等硬件平台。同時我們注意到,Framework并不排斥其他平台,他擁有極高的可移植特性。
(2)模塊化設計Model Design Framework的所有特性都在驅動程序之中實現。而Framework本身則提供了高效的管理這些驅動程序的方法。比方說,你可以load一個驅動,而不需要重新啟動計算機;當你想更新已經load過的驅動,你只需簡單將它unload,然後再load新的驅動就可以了。對我們開發者而言,可以通過編寫我們自己的驅動,來為Framework提供我們自己需要的功能。
3) 快速的啟動時間Fast Startup Time 正如EFI要求的那樣,Framework的啟動時間非常迅速,在這一點上,它一點也不比那些傳統的BIOS落後。
此外,由於Framework是EFI的實現,所有EFI的優點應該說Framework也都具備。
2.3 The life cycle of the Framework Framework的生命周期
Framework的執行,是按照如下的順序來的:
(1)SEC :Security。這個是系統上電後立即進入的一個階段,在這一階段,Intel并沒有做太多的說明,相反,他們說這個階段可以由大家按照自己的需要利用。也就是說,我們可以安排我們自己想要的任何代碼在這個階段,比如一些身份驗證之類的,總之,SEC可以說給開發者帶來了充分的可定***務。
(2)Pre-EFI :正如它的名字一般,這個是在真正的EFI環境之前進入的一個狀態,這個狀態相當重要,以至於Intel花了很多時間來向我們闡述。根據目前的信息,這個階段大概會做很多初始化的工作,會初始化CPU,初始化主板上的一些控制器以及晶片組,更加重要的是,再這個階段內,會使用一種技巧,來迅速的建立起C 代碼的執行環境,也就是說,會建立一個堆棧。這樣,以後機器就可以運行那些由C語言編寫的軟件了。最後PEI內核會按照一種方法來加載所有的PEIM( Pre-EFI Module )。PEIM是一種可以運行在這個階段的一種模塊化的程序,任何人都可以開發自己的PEIM,加載的工作由PEIM Dispatcher完成。全部加載之後,PEI會調用DXE Main并將系統控制權交給下一個階段DXE。
(3)DXE :Driver Execution Environment。這應該說是最激動人心的階段,在這個階段,EFI真正的提供了一個類似OS一樣的東西。在上一個階段PEI,系統已經建立了C代碼執行的環境,那么從這個階段開始,所有的東西,都是用高級語言完成了。進入DXE後,會首先調用各種驅動,比如Video Driver,NIC Driver,Soundcards Driver,USB Driver,PCI Controller Driver等等。完成之後,就開始進行BOOT。而這就是下一個階段了。
(4)BDS :Boot Device Select。在這里,應該會有一個選擇,是進入OS呢?還是去執行那些EFI Applications ?選擇完成之後,就進入下一個階段了。
(5)TSL :Transient System Load。這個階段會按照在BDS階段選擇的結果來做不同的事情,如果選擇了進入OS,那么控制權會被傳遞給Final OS Loader。而如果是要去運行EFI Applications,那么控制權交給Transient OS Boot Loader,這樣就會建立起一個執行環境,之後就可以執行那些EFI Applications了。目前,應該會執行一個叫EFI Shell的程序。而傳統的BIOS Setup也被寫成一個EFI Applications。
(6)RT :Run Time。這個階段就是OS運行的階段。
(7)AL :After Life。這個是OS運行之後的階段,比如關機之類的。但OS崩潰之後也屬於這個階段,也就是說,在系統萬一崩潰之後,如果使用EFI,那么還是可以做許多事情的。
以上就是Framework的執行周期。我們可以看到,Framework除了做很多傳統BIOS的工作之外,還完成了很多其他的工作。比如建立起高級語言執行環境,調用設備驅動等等。最值得注意的是,甚至還有一個執行特定應用程序的機會。
3、Development Tools 開發工具
3.1 Overview 綜述
目前到底使用什么開發工具還不是很明晰。在這次Training上,為了給大家演示,使用的是Microsoft Visual Studio.NET 2003。不過那編譯的是一個Emulator程序,用來模擬真實的EFI環境,況且由於EFI是系統軟件,不太可能直接使用類似VS.NET這樣的高級開發工具。
後來在EFI Driver Development這門課程上,一位HP的工程師認為只要是C Compiler,理論上都可以開發。但是如果要編譯成EBC( EFI Byte Code )代碼的話,那么還得向Intel購買相應的編譯器。(我看了下價格,一個許可證是900多美金!靠!)將代碼編譯成EBC代碼的好處就是,不同的硬件架搆可以共同使用同一套最終的二進制代碼。比如,如果一個設備的Option ROM內的程序是編譯成EBC的話,那么該設備就可以不做任何的修改就可以直接支持IA32/64。而事實上,我們知道,目前Intel的64位安騰處理器與32位的Pentium4處理器在指令集上是不兼容的。那么這又是為什么呢?因為Intel在Framework內,提供了一個叫做EBC Virtual Machine Driver的Protocols。正是靠它,才實現了這樣一個功能。
不過一些第三方廠商到是展示了不少很不錯的開發工具。主要有AMI的開發工具Visual eBIOS,Insyde公司的調式工具H2ODDT,以及American Arium的硬件調式工具以及配套的軟件SourcePoint。
3.2 AMI Visual eBIOS
VEB是一款非常出色的開發工具,由著名的BIOS Venders AMI提供。他為EFI提供了大量的Value Add的工具,AMI認為,Intel的EFI僅僅只是一個骨架(Skeleton)。而他們的VEB則為其穿上了衣服,并為不同的應用目的而做了大量的個性化開發。
3.3 Insyde H2ODDT
由於Insyde公司之前很少進入中國市場,所以我們對其產品了解不深,這款軟件從介紹上看,似乎是專門用於調式Framework的。其余的詳細細節還有待繼續研討。
3.4 American Arium
American Arium是老牌的硬件調式器供應商,他們這次帶來了ECM-50與ECM-XDP。之間的差別似乎僅僅是ECM-XDP只支持那些使用XDP接口的處理器。而ECM-50則支持ITP與XDP接口。同時還演示了配套的軟件SourcePoint。從展示來看,這似乎是目前最好的調式工具,可以直接從硬件上去調式,完全跟蹤。并且支持C Source level的調試。不過根據我們猜測,這套調試工具的價格一定不菲。
4、 EFI Development : Applications & Drivers
EFI 開發 :應用程序與驅動程序
使用EFI的一個很大的好處就是有EFI Application和EFI Drivers。我下來會分別給予討論,事實上,Intel自己也認為,App和Driver在本質沒什么不同。都是一段程序,只是他們的側重點有所不同而已。App需要和用戶交互,而Driver則主要提供某種服務。
4.1 EFI Applications EFI應用程序
4.1.1 Module of the EFI Applications EFI應用程序的類型
目前有好幾種編寫EFI Applications的方法,分別是基於EFI的,基於EFI Library的,基於C Library以及基於C Standard library的。根據Intel的說法,編譯出來的應用程序的體積是一個比一個大,所以,如果想獲得最小的體積,那么就應該使用基於EFI的方法,這也是Intel所推荐的。
4.1.2 A EFI Applications based on EFI 一個基於EFI的簡單應用
最簡單的方法就是親自來看一個EFI App,下面我們就展示一個最簡單的EFI App。
#include <>
EFI_STATUS
InitializeDemoApp(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
SystemTable->ConOut->OutputString(SystemTable->ConOut, L“DEMO Application” ) ;
return EFI_SUCCESS ;
}
這個程序的工作很簡單,就是打印一個字串到終端設備上。類似於我們常見的HelloWorld。從這個程序中,我們可以看出幾點:
(1)所有基於EFI的應用成都必須包含頭文件efi.h
(2)主函數必須被申明成EFI_STATUS
(3)必須在參數前加IN或者OUT或者OPTIONAL來說明參數的類型。這些修飾符是Intel在efidef.h中定義的。目前是空的,不過為了未來的兼容性,所以還是加上的好。
可以看出,單單就入門而言,由於是使用C語言開發,所以入門門檻很低,大多數的工程師都很輕松的加入到開發隊伍中來。至於其他的編程模型,與上述的基於EFI的方法大同小異,只是所使用的庫不同,在此就不在重復了。
4.2 EFI Drivers EFI驅動程序
現在簡單的介紹一下EFI Drivers,事實上驅動程序與一般的應用沒什么區別,只不過驅動不能直接執行,而是在EFI的調度下在後台執行,同時驅動可以接觸硬件。當然也有不接觸硬件的驅動,那叫Service Driver,是用來提供某種服務的,比如EFI EBC Virtual Machine就是一種Service Driver。EFI本身提供了很強大并且的高效的管理這些驅動的方法,當需要一個驅動的時候,我們可以load它,而當有了新版本或者該驅動所管理的硬件已經不在需要的時候,我們可以很方便的unload它。Intel已經提供了一個工具,叫DWW,用他可以很方便的生成基於EFI的驅動程序模型。
5, EFI Shell
5.1 EFI Shell Overview EFI Shell綜述
什么是EFI Shell?首先它是一個基於EFI的應用程序,其次它非常類似我們在Windows中遇到的cmd或者在Linux中的shell。事實上,這就是一個操作環境,一個外殼程序,它負責接收用戶的輸入,將用戶的輸入解釋并告訴內核執行,同時將執行結果顯示出來。它完成和用戶的交互功能。所以,EFI Shell是非常重要的應用程序。
5.2 A EFI Shell Commands EFI Shell命令
EFI Shell使用字符界面和用戶交互,這里列出一些可能用到的命令以便參考。
( 1)pci : 顯示PCI設備或者PCI配置信息
( 2)mm :顯示或者修改內存,I/O以及PCI資源。
( 3)mem :顯示系統內存或者設備內存的情況。
( 4)memmap :顯示由EFI Environment創建的Memory Map。
( 5)drivers :按照EFI Driver 的類型來逐一顯示所有的已經安裝的驅動程序。
( 6)devices :顯示所有已經被EFI Driver控制的設備。
( 7)devtree :按照EFI Driver的類型來顯示設備樹。
( 8)dh :顯示在EFI Environment中的所有的Handles。
( 9)connect :將一個Driver綁定到一個設備并啟動設備。
(10)load :將一個Driver讀入內存。
(11)unload :將一個Driver從內存中卸載。
本文由xinxiaoc 發表於
http://bbs.matwav.com/post/view?bid=103&id=250675&sty=1
2008年10月31日 星期五
2008年10月21日 星期二
C++ Function Templates的基本用法
因為SystemC裏有用到template的語法,所以複習一下C++裏的Function Templates用法
底下的程式是一個取最大值的GetMax Function Templates
T GetMax(T a,T b):T表示可以任意取代各種的資料型態,如果T是int時,代表著傳入了2個int值,回傳1個int值
上面程式執行結果如下:
思考一下:如果想要傳進1個int,1個long,這樣子可以嗎?
答案是可以做,但你必需修改你的template,改成像下面的方式宣告
而你的主程式就可以像下面的方式使用
資料來源:
http://www.cplusplus.com/doc/tutorial/templates.html
底下的程式是一個取最大值的GetMax Function Templates
#include <iostream>
using namespace std;
template <class T>
T GetMax (T a, T b) {
T result;
result = (a>b)? a : b;
return (result);
}
int main () {
int i=5, j=6, k;
long l=10, m=5, n;
// k=GetMax<int>(i,j);
// n=GetMax<long>(l,m);
k=GetMax(i,j);
n=GetMax(l,m);
cout << k << endl;
cout << n << endl;
return 0;
}
T GetMax(T a,T b):T表示可以任意取代各種的資料型態,如果T是int時,代表著傳入了2個int值,回傳1個int值
上面程式執行結果如下:
6
10
思考一下:如果想要傳進1個int,1個long,這樣子可以嗎?
答案是可以做,但你必需修改你的template,改成像下面的方式宣告
template <class T, class U>
T GetMin (T a, U b) {
return (a<b?a:b);
}
而你的主程式就可以像下面的方式使用
int i,j;
long l;
//i = GetMin<int,long> (j,l);
i = GetMin (j,l);
資料來源:
http://www.cplusplus.com/doc/tutorial/templates.html
2008年10月3日 星期五
SystemC Linux開發環境配置
SystemC Linux開發環境配置
SystemC的開發工具有很多種,不過原則上SystemC只是在C++裏增加一個Class,因此基本上任何一個符合ANSI標準的C++編譯工具都可以對systemC程式進行編譯連結來產生可執行檔。
在此我們將介紹如何在Linux環境裏,使用g++來編譯SystemC的程式。我是用4.1.2的g++。
首先請到OSCI網站下載systemc-2.2.0.tgz
http://www.systemc.org/downloads/standards

下載時需要帳號才行下載,所以就申請一個,啟動帳後再回來下載
下載回來後,找個地方把你的systemc-2.2.0.tgz解開
接下來寫個範例程式來測看看
hello.h
Makefile
參數說明:
g++ -o hello hello.cpp -L/usr/systemc/lib-linux -I/usr/systemc/include -lsystemc
hello.cpp:16: error: new types may not be defined in a return type
hello.cpp:16: note: (perhaps a semicolon is missing after the definition of 'hello')
hello.cpp:16: error: two or more data types in declaration of 'sc_main'
hello.cpp: In function 'hello sc_main(int, char**)':
hello.cpp:16: error: new declaration 'hello sc_main(int, char**)'
/usr/systemc/include/sysc/kernel/sc_externs.h:49: error: ambiguates old declaration 'int sc_main(int, char**)'
hello.cpp: In function 'hello sc_main(int, char**)':
hello.cpp:18: error: conversion from 'int' to non-scalar type 'hello' requested
make: *** [all] Error 1
千萬不要以為是sc_main參數有問題,或是回傳值有問題,其實真正的問題點很有可能是沒有加";"喔!
比如:
執行結果如下:
如果是用Windows的可以參考底下這篇文章或 Installing SystemC
如果使用gcc 4.x以上的版本編譯systemc 2.2.0或許會遇到
make[3]: Entering directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src/sysc/utils'
g++ -I. -I. -I../../../../src/sysc/utils -I../../../../src -Wall -DSC_INCLUDE_FX -O3 -c -o sc_utils_ids.o `test -f '../../../../src/sysc/utils/sc_utils_ids.cpp' || echo '../../../../src/sysc/utils/'`../../../../src/sysc/utils/sc_utils_ids.cpp
../../../../src/sysc/utils/sc_utils_ids.cpp: In function ‘int sc_core::initialize()’:
../../../../src/sysc/utils/sc_utils_ids.cpp:110: error: ‘getenv’ is not a member of ‘std’
../../../../src/sysc/utils/sc_utils_ids.cpp:111: error: ‘strcmp’ was not declared in this scope
../../../../src/sysc/utils/sc_utils_ids.cpp: At global scope:
../../../../src/sysc/utils/sc_utils_ids.cpp:119: warning: ‘sc_core::forty_two’ defined but not used
make[3]: *** [sc_utils_ids.o] Error 1
make[3]: Leaving directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src/sysc/utils'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src/sysc'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src'
make: *** [all-recursive] Error 1
---------------------------------------------------------------------------------
please added the following headers in systemc-2.2.0/src/sysc/utils/sc_utils_ids.cpp
#include "string.h"
#include "cstdlib"
然後再重新編譯即可
資料參考來源:
http://blog.csdn.net/funeryoung/archive/2007/11/08/1874515.aspx
http://www.ht-lab.com/howto/vh2sc_tut/vh2sc_tut1.html
一週學會SystemC
安裝SystemC 2.2
SystemC的開發工具有很多種,不過原則上SystemC只是在C++裏增加一個Class,因此基本上任何一個符合ANSI標準的C++編譯工具都可以對systemC程式進行編譯連結來產生可執行檔。
在此我們將介紹如何在Linux環境裏,使用g++來編譯SystemC的程式。我是用4.1.2的g++。
首先請到OSCI網站下載systemc-2.2.0.tgz
http://www.systemc.org/downloads/standards

下載時需要帳號才行下載,所以就申請一個,啟動帳後再回來下載
下載回來後,找個地方把你的systemc-2.2.0.tgz解開
tar xvf systemc-2.2.0.tgz然後
cd systemc-2.2.0然後
mkdir /usr/systemc然後
./configure --prefix=/usr/systemc最後
make做到這裏,我們已經把SystemC的開發環境做好了,我最後在make install時有發生錯誤,但由於是example的部份,所以我就不管它了
make install
接下來寫個範例程式來測看看
hello.h
#ifndef _HELLO_Hhello.cpp
#define _HELLO_H
#include "systemc.h"
SC_MODULE(hello){
SC_CTOR(hello){
cout<<"Hello,SystemC!"<<endl;
}
};
#endif
#if 1上面的hello有2種寫法,但意思是一樣的啦!
#include "hello.h"
#else
#include "systemc.h"
class hello : public sc_module{
public:
hello(sc_module_name name) : sc_module(name){
cout<<"Hello,SystemC!"<<endl;
}
};
#endif
int sc_main(int argc,char** argv){
hello h("hello");
return 0;
}
Makefile
LIB_DIR=-L/usr/systemc/lib-linux你也可以使用g++ hello.cpp -I/usr/systemc/include -L/usr/systemc/lib-linux -o hello -lsystemc直接下命令編譯
INC_DIR=-I/usr/systemc/include
LIB=-lsystemc
APP=hello
all:
g++ -o $(APP) $(APP).cpp $(LIB_DIR) $(INC_DIR) $(LIB)
clean:
rm -rf $(APP)
參數說明:
- -I/usr/systemc/include 告訴g++去/usr/systemc/include底下尋找include檔案,也就是我們寫的systemc.h路徑
-L/usr/systemc/lib-linux 告訴ld去/usr/systemc/lib-linux底下尋找library檔案
-o hello 最後輸出一個執行檔,檔名為hello
-lsystemc 靠訴ld要引用libsystemc.a這個函式庫
g++ -o hello hello.cpp -L/usr/systemc/lib-linux -I/usr/systemc/include -lsystemc
hello.cpp:16: error: new types may not be defined in a return type
hello.cpp:16: note: (perhaps a semicolon is missing after the definition of 'hello')
hello.cpp:16: error: two or more data types in declaration of 'sc_main'
hello.cpp: In function 'hello sc_main(int, char**)':
hello.cpp:16: error: new declaration 'hello sc_main(int, char**)'
/usr/systemc/include/sysc/kernel/sc_externs.h:49: error: ambiguates old declaration 'int sc_main(int, char**)'
hello.cpp: In function 'hello sc_main(int, char**)':
hello.cpp:18: error: conversion from 'int' to non-scalar type 'hello' requested
make: *** [all] Error 1
千萬不要以為是sc_main參數有問題,或是回傳值有問題,其實真正的問題點很有可能是沒有加";"喔!
比如:
SC_MODULE(hello){
SC_CTOR(hello){
cout<<"Hello,SystemC!"<<endl;
}
}
就是在最後的"}"後面,還必需接一個";",才不會有錯誤。執行結果如下:
[root@svn hello]# ./hello
SystemC 2.2.0 --- Oct 3 2008 11:10:01
Copyright (c) 1996-2006 by all Contributors
ALL RIGHTS RESERVED
Hello,SystemC!
如果是用Windows的可以參考底下這篇文章或 Installing SystemC
如果使用gcc 4.x以上的版本編譯systemc 2.2.0或許會遇到
make[3]: Entering directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src/sysc/utils'
g++ -I. -I. -I../../../../src/sysc/utils -I../../../../src -Wall -DSC_INCLUDE_FX -O3 -c -o sc_utils_ids.o `test -f '../../../../src/sysc/utils/sc_utils_ids.cpp' || echo '../../../../src/sysc/utils/'`../../../../src/sysc/utils/sc_utils_ids.cpp
../../../../src/sysc/utils/sc_utils_ids.cpp: In function ‘int sc_core::initialize()’:
../../../../src/sysc/utils/sc_utils_ids.cpp:110: error: ‘getenv’ is not a member of ‘std’
../../../../src/sysc/utils/sc_utils_ids.cpp:111: error: ‘strcmp’ was not declared in this scope
../../../../src/sysc/utils/sc_utils_ids.cpp: At global scope:
../../../../src/sysc/utils/sc_utils_ids.cpp:119: warning: ‘sc_core::forty_two’ defined but not used
make[3]: *** [sc_utils_ids.o] Error 1
make[3]: Leaving directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src/sysc/utils'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src/sysc'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/Pratik/SystemC/systemc-2.2.0/objdir/src'
make: *** [all-recursive] Error 1
---------------------------------------------------------------------------------
please added the following headers in systemc-2.2.0/src/sysc/utils/sc_utils_ids.cpp
#include "string.h"
#include "cstdlib"
然後再重新編譯即可
資料參考來源:
http://blog.csdn.net/funeryoung/archive/2007/11/08/1874515.aspx
http://www.ht-lab.com/howto/vh2sc_tut/vh2sc_tut1.html
一週學會SystemC
安裝SystemC 2.2
2008年10月1日 星期三
周杰倫在-稻香歌詞
周杰倫在《稻香》開頭第一段就唱,「對這個世界如果你有太多的抱怨,跌倒了就不敢繼續往前走,為什麼人要這麼的脆弱、墮落…」,提醒大家不要以抱怨代替感激,要傳達的概念就是「知足」。
《稻 香》 詞:周杰倫 曲:周杰倫
對這個世界如果你有太多的抱怨
跌倒了就不敢繼續往前走
為什麼人要這麼的脆弱 墮落
請你打開電視看看
多少人為生命在努力勇敢的走下去
我們是不是該知足
珍惜一切 就算沒有擁有
還記得你說家是唯一的城堡 隨著稻香河流繼續奔跑
微微笑 小時候的夢我知道
不要哭讓螢火蟲帶著你逃跑 鄉間的歌謠永遠的依靠
回家吧 回到最初的美好
不要這麼容易就想放棄 就像我說的
追不到的夢想 換個夢不就得了
為自己的人生鮮艷上色 先把愛塗上喜歡的顏色
笑一個吧 功成名就不是目的
讓自己快樂快樂這才叫做意義
童年的紙飛機 現在終於飛回我手裡
所謂的那快樂 赤腳在田里追蜻蜓追到累了
偷摘水果被蜜蜂給叮到怕了 誰在偷笑呢
我靠著稻草人吹著風唱著歌睡著了
哦 哦 午後吉它在蟲鳴中更清脆
哦 哦 陽光灑在路上就不怕心碎
珍惜一切 就算沒有擁有
* 還記得你說家是唯一的城堡 隨著稻香河流繼續奔跑
微微笑 小時候的夢我知道
不要哭讓螢火蟲帶著你逃跑 鄉間的歌謠永遠的依靠
回家吧 回到最初的美好
資料來源:
http://www.epochtimes.com/b5/8/9/22/n2271481.htm
《稻 香》 詞:周杰倫 曲:周杰倫
對這個世界如果你有太多的抱怨
跌倒了就不敢繼續往前走
為什麼人要這麼的脆弱 墮落
請你打開電視看看
多少人為生命在努力勇敢的走下去
我們是不是該知足
珍惜一切 就算沒有擁有
還記得你說家是唯一的城堡 隨著稻香河流繼續奔跑
微微笑 小時候的夢我知道
不要哭讓螢火蟲帶著你逃跑 鄉間的歌謠永遠的依靠
回家吧 回到最初的美好
不要這麼容易就想放棄 就像我說的
追不到的夢想 換個夢不就得了
為自己的人生鮮艷上色 先把愛塗上喜歡的顏色
笑一個吧 功成名就不是目的
讓自己快樂快樂這才叫做意義
童年的紙飛機 現在終於飛回我手裡
所謂的那快樂 赤腳在田里追蜻蜓追到累了
偷摘水果被蜜蜂給叮到怕了 誰在偷笑呢
我靠著稻草人吹著風唱著歌睡著了
哦 哦 午後吉它在蟲鳴中更清脆
哦 哦 陽光灑在路上就不怕心碎
珍惜一切 就算沒有擁有
* 還記得你說家是唯一的城堡 隨著稻香河流繼續奔跑
微微笑 小時候的夢我知道
不要哭讓螢火蟲帶著你逃跑 鄉間的歌謠永遠的依靠
回家吧 回到最初的美好
資料來源:
http://www.epochtimes.com/b5/8/9/22/n2271481.htm
2008年9月26日 星期五
Android 1.0 SDK Released
更新速度真快@@
Android 1.0 SDK已經在2008/09/24釋放出來可以下載囉!
有興趣的人快去載來玩看看吧!
http://android-developers.blogspot.com/2008/09/announcing-android-10-sdk-release-1.html
0.9->1.0改變了些什麼呢?
http://code.google.com/android/migrating/0.9-1.0/changes-overview.html
1.0 Source Code下載網址
http://code.google.com/p/android/downloads/list
主要項目如下四個:
Linux 2.6.25 for Android 1.0 SDK,Release 1
Source for WebKit as included in Android 1.0 SDK, Release 1
Emulator for Android 1.0 SDK, Release 1
Android Development Tools: Plugins 0.8.0 for Eclipse 3.3/3.4, for Android SDK 1.0_r1(source only)
Android 1.0 SDK已經在2008/09/24釋放出來可以下載囉!
有興趣的人快去載來玩看看吧!
http://android-developers.blogspot.com/2008/09/announcing-android-10-sdk-release-1.html
0.9->1.0改變了些什麼呢?
http://code.google.com/android/migrating/0.9-1.0/changes-overview.html
- Content Provider
- Device Hardware
- Maps
- Media
- NetWork
- Package manager
- Text input
- Test
- Views
- XML
- Widgets
Settings.System加入了許多新的Wi-Fi設定,用來提供儲存Wi-Fi的狀態。
Camera增加了新的介面,名為Camera.ShutterCallback,用來在拍照後快門關閉後的事件回呼函式。
SensorManager增加了一些新的fields。
ItemizedOverlay增加新的方法(methods)到overlays。
MyLocationOverlay類別增加一個新的方法去偵測是否有指南針被顯示在MapView以及接收sensor位置改變時的事件。
在AudioManager裏加入了新的載入/卸載音效的方法。
MediaMetadataRetriver類別在此版尚不支援。
android.media.MediaPlayer.getFrameAt()在此版本也不支援。
android.net.wifi新增了一些類別用來保持wi-fi無線喚醒及識別配對加密的WPA功能,這也改變了其它相關類別的fields及methods。
org.apache.http.impl已被加入到這個平台
在android.test裏增加了一些新的類別及介面,如建置包含測試裝置的測試環境,測試單元及測試包。
新增junit.runner套件。
新增android.test.mock套件含工具類別,用來提供stub或mock來進行Android框架區塊單元的各種測試。
新增android.test.suitebuilder套件含工具類別,用來提供test runner classes。
新增數個XML屬性給View物件。
新增支援音效功能。
你已可以監聽sensors(感知器)的改變狀態。
WebView加入新的透明物件用來給移動的WebView跨越process的範圍。
WebView加入新方法給managing scrollbar overlays.
org.xmlpull.v1在這平台已可以使用
verifyDrawable(Drawable)這個方法的屬性已從公開(public)改變成保護(protected).還有一些小widget有做一些變動。
1.0 Source Code下載網址
http://code.google.com/p/android/downloads/list
主要項目如下四個:
Linux 2.6.25 for Android 1.0 SDK,Release 1
Source for WebKit as included in Android 1.0 SDK, Release 1
Emulator for Android 1.0 SDK, Release 1
Android Development Tools: Plugins 0.8.0 for Eclipse 3.3/3.4, for Android SDK 1.0_r1(source only)
2008年9月25日 星期四
[轉載]斷點續傳技術
北京理工大學 20981 陳罡
要做手機斷點續傳了,網上的代碼有很多,但是多數要麼是過於復雜,要麼是用java,pascal之類的語言編寫的。都不適合直接用在手機上,無奈之下我這個懶人開始動手自己寫了。
(1)手機斷點續傳的未來?
手機上開發應用程序的時候,或多或少都要用到gprs連接互聯網(Internet),從互聯網上的服務器中把數據取出來,然後存儲到手機上,利用專門的客戶端來查看。這就可以美其名曰“在線更新”了。隨着智能手機的處理能力越來越強以及gprs升級在即(也就是傳說中的2.5G或3G了),手機的網絡應用更加惹人注意,尤其是在RSS手機新聞組、手機mail下載大附件、手機電視實時緩沖視頻流、在或者在線聽mp3、下載圖鈴之類的3G手機網絡應用上,是否具有斷點續傳的功能尤其重要。這項技術還將發展相當長的一段時間(除非移動把什麼cmwap,cmnet都統一了,目前還沒有看到有統一的跡象)。
(2)手機斷點續傳的實質?
手機上的應用越花俏就必然對應着需要下載的數據文件就會越大。目前絕大多數的手機瀏覽器,都支持gprs下載功能,所不同的是,絕大多數都沒有斷點續傳的功能。比如你要下載一首几百K的mp3,下載到2/3的時候,突然進了地鐵或者信號不好,斷開了,那就意味着剛剛的那2/3已經浪費了。再次下載的時候,就需要重新下載了。斷點續傳這個技術就是用來解決這個問題的,它的實質就是如果程序開始准備重新下載的時候,先檢查一下,已經下載了多少了,然後再接着剛剛下載過的地方繼續,接着下載。
(3)傳統斷點續傳的原理?
首先,斷點續傳不是什麼高深的技術,它是標准的http協議中已經定義了很久的東西;其次,需要服務器支持,我這邊使用的是apache的服務器,對斷點續傳支持得很好。
其實斷點續傳的原理很簡單,就是在http的請求上和一般的下載有所不同而已。
假設服務器域名為www.5mbox.com,文件名為/bbs/mp1.mp3
當web瀏覽器請求從服務器上的一個文時,所發出的請求如下:
服務器收到請求以後,會回應如下內容:
...後面跟着就是數據了。
斷點續傳,也就是要從文件已經下載的地方開始繼續下載。所以在客戶端瀏覽器傳給
web服務器的時候要多加一條信息--從哪里開始。
下面是用自己編的一個"瀏覽器"來傳遞請求信息給web服務器,要求從2000070字節開始。
仔細看一下就會發現多了一行RANGE: bytes=2000070-
這一行的意思就是告訴服務器mp1.mp3這個文件從2000070字節開始傳,前面的字節不用傳了。
服務器收到這個請求以后,返回的信息如下:
。。。二進制數據
和前面服務器返回的信息比較一下,就會發現增加了一行:
Content-Range=bytes 2000070-106786027/106786028
返回的代碼也改為206了,而不再是200了。
知道了以上原理,就可以進行斷點續傳的編程了。
(4)斷點續傳的實現
懶得一個個解釋,直接上代碼了(請注意,下面的代碼是在win32上做驗證用的,不是給手機用的),採用c++編寫,dev-c++ 4.9.9.2編譯的,我相信g++都行vs系列自然不在話下:
M5HttpDown.h文件的內容:
M5HttpDown.cpp的文件內容:(作家侯杰曾經說過,源碼之下了無秘密,不需要我解釋什麼了吧。。。)
貼上整個dev-c++的工程,感興趣的朋友直接下了玩玩。
nettest.rar
運行nettest.exe,就會在其當前目錄生成一個叫test.mp3的文件,螢幕上還顯示下載進度。
可以隨時關閉,然後再次打開,看看斷點續傳的效果。
下面的這個是將上述代碼,通過RSocket移植到symbian s60 2nd平台上的測試程序(我做了一些修改使之可以同時支持cmwap和cmnet的gprs環境,再此鄙視一下移動的行為),
出于公司的利益考慮,就不開放代碼了。
NetTestSIS.rar
當調用cmwap conn的時候,接入點要選擇"移動夢網"或者"nokia.com";
當調用cmnet conn的時候,接入點要選擇"gprs連接互聯網";
看到螢幕上顯示"connected"的時候,選擇"resume",就會開始斷點續傳過程。
對於cmwap由於移動有推送頁面,在程序里面加入了效驗,如果有推送頁面,
程序會顯示"check failed",這時,再按一次"resume"即可。
更換連網方式之前,需要選擇"stop",斷開gprs連接,然後再連。
還有一個小小的意外是對于移動的網關來說,Content-Length這是標准http服務器返回的;
但是移動的代理返回的結果是Content-length這個"l"是小寫的,這個細節一定要注意才行喔!!
呵呵,期待5mbox網路版早日成功。
資料來源:
http://blog.chinaunix.net/u/26691/showart_433628.html
http://blog.chinaunix.net/u/26691/showart_433631.html
要做手機斷點續傳了,網上的代碼有很多,但是多數要麼是過於復雜,要麼是用java,pascal之類的語言編寫的。都不適合直接用在手機上,無奈之下我這個懶人開始動手自己寫了。
(1)手機斷點續傳的未來?
手機上開發應用程序的時候,或多或少都要用到gprs連接互聯網(Internet),從互聯網上的服務器中把數據取出來,然後存儲到手機上,利用專門的客戶端來查看。這就可以美其名曰“在線更新”了。隨着智能手機的處理能力越來越強以及gprs升級在即(也就是傳說中的2.5G或3G了),手機的網絡應用更加惹人注意,尤其是在RSS手機新聞組、手機mail下載大附件、手機電視實時緩沖視頻流、在或者在線聽mp3、下載圖鈴之類的3G手機網絡應用上,是否具有斷點續傳的功能尤其重要。這項技術還將發展相當長的一段時間(除非移動把什麼cmwap,cmnet都統一了,目前還沒有看到有統一的跡象)。
(2)手機斷點續傳的實質?
手機上的應用越花俏就必然對應着需要下載的數據文件就會越大。目前絕大多數的手機瀏覽器,都支持gprs下載功能,所不同的是,絕大多數都沒有斷點續傳的功能。比如你要下載一首几百K的mp3,下載到2/3的時候,突然進了地鐵或者信號不好,斷開了,那就意味着剛剛的那2/3已經浪費了。再次下載的時候,就需要重新下載了。斷點續傳這個技術就是用來解決這個問題的,它的實質就是如果程序開始准備重新下載的時候,先檢查一下,已經下載了多少了,然後再接着剛剛下載過的地方繼續,接着下載。
(3)傳統斷點續傳的原理?
首先,斷點續傳不是什麼高深的技術,它是標准的http協議中已經定義了很久的東西;其次,需要服務器支持,我這邊使用的是apache的服務器,對斷點續傳支持得很好。
其實斷點續傳的原理很簡單,就是在http的請求上和一般的下載有所不同而已。
假設服務器域名為www.5mbox.com,文件名為/bbs/mp1.mp3
當web瀏覽器請求從服務器上的一個文時,所發出的請求如下:
GET /bbs/mp1.mp3 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Connection: Keep-Alive
服務器收到請求以後,會回應如下內容:
200
Content-Length=106786028
Accept-Ranges=bytes
Date=Mon, 30 Apr 2001 12:56:11 GMT
ETag=W/"02ca57e173c11:95b"
Content-Type=application/octet-stream
Server=Microsoft-IIS/5.0
Last-Modified=Mon, 30 Apr 2001 12:56:11 GMT
...後面跟着就是數據了。
斷點續傳,也就是要從文件已經下載的地方開始繼續下載。所以在客戶端瀏覽器傳給
web服務器的時候要多加一條信息--從哪里開始。
下面是用自己編的一個"瀏覽器"來傳遞請求信息給web服務器,要求從2000070字節開始。
GET /bbs/mp1.mp3 HTTP/1.0
User-Agent: NetFox
RANGE: bytes=2000070-
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
仔細看一下就會發現多了一行RANGE: bytes=2000070-
這一行的意思就是告訴服務器mp1.mp3這個文件從2000070字節開始傳,前面的字節不用傳了。
服務器收到這個請求以后,返回的信息如下:
206
Content-Length=106786028
Content-Range=bytes 2000070-106786027/106786028
Date=Mon, 30 Apr 2001 12:55:20 GMT
ETag=W/"02ca57e173c11:95b"
Content-Type=application/octet-stream
Server=Microsoft-IIS/5.0
Last-Modified=Mon, 30 Apr 2001 12:55:20 GMT
。。。二進制數據
和前面服務器返回的信息比較一下,就會發現增加了一行:
Content-Range=bytes 2000070-106786027/106786028
返回的代碼也改為206了,而不再是200了。
知道了以上原理,就可以進行斷點續傳的編程了。
(4)斷點續傳的實現
懶得一個個解釋,直接上代碼了(請注意,下面的代碼是在win32上做驗證用的,不是給手機用的),採用c++編寫,dev-c++ 4.9.9.2編譯的,我相信g++都行vs系列自然不在話下:
M5HttpDown.h文件的內容:
#ifndef _M5_HTTP_DOWN_H_
#include <process.h>
#include <wininet.h>
#include <winsock2.h>
#include <stdio.h>
#define HTTP_DEBUG_MODE 1
#define HTTP_WEB_PORT 80
#define HTTP_TEMP_BUF_LEN 120
#define HTTP_SEND_BUF_LEN 256
#define HTTP_RECV_BUF_LEN 4096
#define HTTP_HDR_OK "200 OK"
#define HTTP_HDR_FILE_LEN "Content-Length: "
#define HTTP_HDR_DIV "\r\n"
#define HTTP_HDR_END "\r\n\r\n"
#define HTTP_PREFIX "http://"
#define HTTPS_PREFIX "https://"
// 這里分成了兩個get字符串的定義,主要是為了兼容普通的http下載
// 以及支持斷點續傳的http下載
<pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #999;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%">#define HTTP_COMMON_GET "GET /%s HTTP/1.1\r\n\
User-Agent: Opera 8.0\r\n\
Host: %s:%d\r\nAccept: */\
*\r\nConnection: Keep-Alive\r\n\r\n"
#define HTTP_RESUME_GET "GET /%s HTTP/1.1\r\n\
User-Agent: Opera 8.0\r\n\
Host: %s:%d\r\nAccept: */\
*\r\nRANGE: bytes=%d-\r\n\
Connection: Keep-Alive\r\n\r\n"
</pre>
// 這里為了方便起見,就沒有用什麼notifier或者虛擬函數之類的東西了,直接回調
// recv_buf:里面裝着二進制數據,就是要下載的文件中的數據部分
// recv_len:數據的長度
// data:既然是回調函數,就需要允許caller把相關的數據結搆也帶進來。
typedef void (*RECV_CALLBACK)(char * recv_buf, int recv_len, void * data) ;
class CM5HttpDown {
protected:
// socket data
SOCKET m_sock ;
bool m_running ; // 標志是否運行
bool m_is_first_resp ; // 第一次收到數據的標志,用于跳過服務器的http頭
char * m_web_addr ; // 存放從uri中解析出來的網址
char * m_web_fname ; // 存放uri中的文件名
int m_web_port ; // uri中的服務器端口好,缺省值是80
char * m_recv_buf ; // 接收緩沖區
int m_total_bytes ; // uri中文件的總大小,單位字節
int m_recv_bytes; // 已經接收了多少字節,用于斷點續傳中接着傳
// custom defined receive handler
RECV_CALLBACK m_custom_callback ; // 回調函數指針
void * m_custom_data ; // call的自定義數據結搆指針
public:
// common receive thread func
static void recv_thread(void * data) ; // 線程函數,必須是靜態的
void recv_thread_handler() ; // 在線程函數中調用,是實際上的接收函數
protected:
// uri解析函數,能夠把諸如http://www.5mbox.com/bbs/mp1.mp3的uri分解為
// web_addr : www.5mbox.com
// web_fname : bbs/mp1.mp3
bool parse_uri(char * uri,
char * web_addr, char * web_fname, int * web_port) ;
// 第一次收到http回應的時候,解析出來文件的大小(toal_length),以及需要跳過的長度
// (jumplen),這樣就可以只把有用數據給call傳過去了,而無用的http頭就丟棄了。
bool parse_webfile_info(char * recv_buf,
int * total_length, int * jump_len) ;
// 用于把指定的field的值字符串從http頭中讀取出來,例如回應http的頭為:
// 206
// Content-Length: 106786028
// Content-Range: bytes 2000070-106786027/106786028
// Date=Mon, 30 Apr 2001 12:55:20 GMT
// ETag=W/"02ca57e173c11:95b"
// Content-Type: application/octet-stream
// Server=Microsoft-IIS/5.0
// Last-Modified=Mon, 30 Apr 2001 12:55:20 GMT
// 該函數就可以把比方說"Content-Length: "的數據"106786028"給取出來
bool get_resp_field(char * recv_buf,
char * field_name, char * end_flag, char * res) ;
// socket的常規操作函數
bool init_sock(char * server_name, int server_port) ;
bool send_req(char * req_str, int req_len) ;
bool close_sock() ;
public:
CM5HttpDown() ;
~CM5HttpDown() ;
bool is_running() {return m_running ; }
int http_total_size() { return m_total_bytes ; }
int http_recv_size() { return m_recv_bytes ; }
// 這個就是主要的http下載函數了,使用的時候直接調用這個函數就行了。
// uri : 要下載的web文件地址,例如http://www.5mbox.com/bbs/mp1.mp3
// custom_func : 回調函數,收到二進制數據的時候,會自動調用該函數
// custom_data : call的自定義數據類型
// recv_bytes : 已經接收了多少個字節的數據,用于斷點續傳。如果該數值為0
// 則釆用普通的get方法下載;如果不為0,則釆用斷點續傳接着下載
bool http_down(char * uri,
RECV_CALLBACK custom_func, void * custom_data,
int recv_bytes = 0) ;
// 下載過程中強制關閉下載用的
bool http_stop() ;
} ;
#endif
M5HttpDown.cpp的文件內容:(作家侯杰曾經說過,源碼之下了無秘密,不需要我解釋什麼了吧。。。)
#include "M5HttpDown.h"
#include <string.h>
CM5HttpDown::CM5HttpDown()
{
m_sock = (SOCKET)(NULL) ;
m_running = false ;
m_is_first_resp = true ;
m_web_addr = NULL ;
m_web_fname = NULL ;
m_custom_callback = NULL ;
m_custom_data = NULL ;
m_total_bytes = 0 ;
m_recv_bytes = 0 ;
m_recv_buf = new char [HTTP_RECV_BUF_LEN] ;
memset(m_recv_buf, 0, HTTP_RECV_BUF_LEN) ;
}
CM5HttpDown::~CM5HttpDown()
{
if(m_recv_buf) delete [] m_recv_buf ;
if(m_web_addr) delete [] m_web_addr ;
if(m_web_fname) delete [] m_web_fname ;
}
void CM5HttpDown::recv_thread(void * data)
{
CM5HttpDown * http_down_ptr = static_cast<CM5HttpDown *>(data) ;
http_down_ptr->recv_thread_handler() ;
_endthread() ;
}
void CM5HttpDown::recv_thread_handler()
{
fd_set recv_fd ;
struct timeval tmv ;
int recv_bytes ;
int jump_length ;
while(m_running) {
FD_ZERO(&recv_fd) ;
FD_CLR(m_sock, &recv_fd) ;
FD_SET(m_sock, &recv_fd) ;
tmv.tv_sec = 1 ;
tmv.tv_usec = 0 ;
if(select(m_sock+1, &recv_fd, NULL, NULL, &tmv) < 0) {
#ifdef HTTP_DEBUG_MODE
printf("select recv failed !\n") ;
fflush(stdout) ;
#endif
return ;
}
if(FD_ISSET(m_sock, &recv_fd)) {
// time to read
recv_bytes = 0 ;
jump_length = 0 ;
memset(m_recv_buf, 0, HTTP_RECV_BUF_LEN) ;
recv_bytes = recv(m_sock, m_recv_buf, HTTP_RECV_BUF_LEN, 0) ;
if(recv_bytes > 0) {
if(m_is_first_resp) {
if(parse_webfile_info(m_recv_buf, &m_total_bytes, &jump_length)) {
// 這里比較亂,意思是:如果是斷點續傳的話,第一次收到response
// 的時候,m_recv_bytes就有數據,此時整個文件的大小應該是
// 服務器返回的content-length長度加上已經接收過了的數據長度
if(m_recv_bytes > 0) m_total_bytes += m_recv_bytes ;
#ifdef HTTP_DEBUG_MODE
printf("file length : %d\n", m_total_bytes) ;
#endif
m_recv_bytes += (recv_bytes - jump_length) ;
(*m_custom_callback)(m_recv_buf + jump_length,
recv_bytes - jump_length,
m_custom_data) ;
}
m_is_first_resp = false ;
continue ;
} else {
// common receive procdure
if((m_recv_bytes + recv_bytes) > m_total_bytes) {
recv_bytes = m_total_bytes - m_recv_bytes ;
m_recv_bytes = m_total_bytes ;
} else {
m_recv_bytes += recv_bytes ;
}
(*m_custom_callback)(m_recv_buf, recv_bytes, m_custom_data) ;
}
} else if(recv_bytes == 0) {
// conn down
#ifdef HTTP_DEBUG_MODE
printf("disconn...\n") ;
#endif
m_running = false ;
}
}
}
}
bool CM5HttpDown::send_req(char * req_str, int req_len)
{
fd_set send_fd ;
struct timeval tmv ;
int send_bytes ;
if(!m_sock || req_len <= 0 || req_str == NULL) return false ;
FD_ZERO(&send_fd) ;
FD_CLR(m_sock, &send_fd) ;
FD_SET(m_sock, &send_fd) ;
tmv.tv_sec = 1 ;
tmv.tv_usec = 0 ;
if(select(m_sock+1, NULL, &send_fd, NULL, &tmv) < 0) {
#ifdef HTTP_DEBUG_MODE
printf("select send failed !\n") ;
fflush(stdout) ;
#endif
return false ;
}
if(FD_ISSET(m_sock, &send_fd)) {
send_bytes = send(m_sock, req_str, req_len, 0) ;
if(req_len != send_bytes) return false ;
return true ;
}
return false ;
}
bool CM5HttpDown::parse_uri(char * uri, char * web_addr,
char * web_fname, int * web_port)
{
char * ptr_a = NULL ;
char * ptr_b = NULL ;
*web_port = HTTP_WEB_PORT ;
if(!uri) return false ;
// search for http or https prefix
ptr_a = uri ;
if(!strncmp(ptr_a, HTTP_PREFIX, strlen(HTTP_PREFIX)))
ptr_a = uri + strlen(HTTP_PREFIX) ;
else if(!strncmp(ptr_a, HTTPS_PREFIX, strlen(HTTPS_PREFIX)))
ptr_a = uri + strlen(HTTPS_PREFIX) ;
// get web_addr without "http://" or "https://" prefix
ptr_b = strchr(ptr_a, '/');
if(ptr_b) {
memcpy(web_addr, ptr_a, strlen(ptr_a) - strlen(ptr_b));
if(ptr_b + 1) {
// get web file name
memcpy(web_fname, ptr_b + 1, strlen(ptr_b) - 1);
web_fname[strlen(ptr_b) - 1] = '\0' ;
}
} else memcpy(web_addr, ptr_a, strlen(ptr_a)) ;
if(ptr_b) web_addr[strlen(ptr_a) - strlen(ptr_b)] = '\0' ;
else web_addr[strlen(ptr_a)] = '\0' ;
// search for uri port number
ptr_a = strchr(web_addr, ':') ;
if(ptr_a) *web_port = atoi(ptr_a + 1);
else *web_port = HTTP_WEB_PORT ;
return true ;
}
bool CM5HttpDown::get_resp_field(char * recv_buf, char * field_name, char * end_flag, char * res)
{
char * start_ptr = NULL ;
char * end_ptr = NULL ;
start_ptr = strstr(recv_buf, field_name) ;
if(start_ptr == NULL) return false ;
start_ptr += strlen(field_name) ;
end_ptr = strstr(start_ptr, end_flag) ;
if(end_ptr == NULL) return false ;
memcpy(res, start_ptr, end_ptr - start_ptr) ;
res[end_ptr - start_ptr] = '\0' ;
return true ;
}
bool CM5HttpDown::parse_webfile_info(char * recv_buf, int * file_length, int * jump_len)
{
char tmp_str[50] ;
char * offset_str = NULL ;
#ifdef HTTP_DEBUG_MODE
printf("%s\n", recv_buf) ;
#endif
// get file length
if(!get_resp_field(recv_buf, HTTP_HDR_FILE_LEN, HTTP_HDR_DIV, tmp_str))
return false ;
*file_length = atoi(tmp_str) ;
// get current offset
offset_str = strstr(recv_buf, HTTP_HDR_END) ;
if(offset_str == NULL) return false ;
*jump_len = (int)(offset_str + strlen(HTTP_HDR_END) - recv_buf) ;
return true ;
}
bool CM5HttpDown::init_sock(char * server_name, int server_port)
{
struct sockaddr_in sock_in ;
struct hostent * he ;
{
// only worked in dos
WSADATA wsadata ;
if (WSAStartup(0x0202, &wsadata) != 0) return false ;
}
// get server ip address
he = gethostbyname(server_name) ;
if (!he) sock_in.sin_addr.s_addr = inet_addr(server_name) ;
else {
sock_in.sin_addr.s_addr = *(unsigned long *)(he->h_addr_list[0]) ;
#ifdef HTTP_DEBUG_MODE
printf("ip : %s\n", inet_ntoa(sock_in.sin_addr)) ;
#endif
}
sock_in.sin_family = AF_INET;
sock_in.sin_port = htons(server_port);
m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
if(!connect(m_sock,(struct sockaddr *)(&sock_in), sizeof(sock_in))) {
HANDLE thread_handle ;
m_running = true ;
thread_handle = (HANDLE)(_beginthread(CM5HttpDown::recv_thread, 0,(void *)(this))) ;
return true ;
}
return false ;
}
bool CM5HttpDown::close_sock()
{
if(m_running) {
m_running = false ;
Sleep(1000) ;
if(m_sock) closesocket(m_sock) ;
}
{
// only worked in dos
WSACleanup() ;
}
return true ;
}
bool CM5HttpDown::http_down(char * uri,
RECV_CALLBACK custom_func, void * custom_data,
int recv_bytes)
{
char buffer[HTTP_SEND_BUF_LEN] ;
memset(buffer, 0, HTTP_TEMP_BUF_LEN) ;
if(uri == NULL) return false ;
m_recv_bytes = recv_bytes ;
m_custom_callback = custom_func ;
m_custom_data = custom_data ;
m_web_addr = new char [HTTP_TEMP_BUF_LEN] ;
m_web_fname = new char [HTTP_TEMP_BUF_LEN] ;
memset(m_web_addr, 0, HTTP_TEMP_BUF_LEN) ;
memset(m_web_fname, 0, HTTP_TEMP_BUF_LEN) ;
parse_uri(uri, m_web_addr, m_web_fname, &m_web_port) ;
if(m_recv_bytes == 0) {
snprintf(buffer, HTTP_SEND_BUF_LEN, HTTP_COMMON_GET,
m_web_fname, m_web_addr, m_web_port) ;
} else {
snprintf(buffer, HTTP_SEND_BUF_LEN, HTTP_RESUME_GET,
m_web_fname, m_web_addr, m_web_port, m_recv_bytes) ;
}
#ifdef HTTP_DEBUG_MODE
printf("%s\n", buffer) ;
#endif
m_running = true ;
if(!init_sock(m_web_addr, m_web_port)) return false ;
// send the request
return send_req(buffer, strlen(buffer)) ;
}
bool CM5HttpDown::http_stop()
{
return close_sock() ;
}
貼上整個dev-c++的工程,感興趣的朋友直接下了玩玩。
nettest.rar
運行nettest.exe,就會在其當前目錄生成一個叫test.mp3的文件,螢幕上還顯示下載進度。
可以隨時關閉,然後再次打開,看看斷點續傳的效果。
下面的這個是將上述代碼,通過RSocket移植到symbian s60 2nd平台上的測試程序(我做了一些修改使之可以同時支持cmwap和cmnet的gprs環境,再此鄙視一下移動的行為),
出于公司的利益考慮,就不開放代碼了。
NetTestSIS.rar
當調用cmwap conn的時候,接入點要選擇"移動夢網"或者"nokia.com";
當調用cmnet conn的時候,接入點要選擇"gprs連接互聯網";
看到螢幕上顯示"connected"的時候,選擇"resume",就會開始斷點續傳過程。
對於cmwap由於移動有推送頁面,在程序里面加入了效驗,如果有推送頁面,
程序會顯示"check failed",這時,再按一次"resume"即可。
更換連網方式之前,需要選擇"stop",斷開gprs連接,然後再連。
還有一個小小的意外是對于移動的網關來說,Content-Length這是標准http服務器返回的;
但是移動的代理返回的結果是Content-length這個"l"是小寫的,這個細節一定要注意才行喔!!
呵呵,期待5mbox網路版早日成功。
資料來源:
http://blog.chinaunix.net/u/26691/showart_433628.html
http://blog.chinaunix.net/u/26691/showart_433631.html
[轉貼]EFI/UEFI BIOS 入門 : All For Beginners – 另附深入學習指南以及有用的URL連接
我們已經使用BIOS超過了二十年.可是直到今天還友許多朋友不知道BIOS到底是什麼,以及它主要做些什麼事情,它在整個個人計算機之中所處的地位如何.事實上,BIOS是整個計算機系統中最重要的底層系統軟體.二十多年來,中國的程序員們紛紛忽略了BIOS,或者由BIOS衍生出的開發技術,相反,我們對如何調整一兩個BIOS設置津津樂道.今天,BIOS業界開始悄悄的變革,EFI或者UEFI的到來即將改變世界,從而徹底改變我們對過去的計算機啟動過程的認識.但是我們中國的開發者們仍然在談論JAVA或者.NET,我想,是到了清晰的研究BIOS的時候了.
小生不才,但也願意就我所學,貢獻成一篇簡短的入門文章,帶領大家進入BIOS這個有趣而又充滿了神秘的地域,我們一起來探究BIOS,尤其是探究下一代個人計算機的基礎系統軟體,或者說基礎固件:UEFI bios的方方面面.由于類似的文章網上也比較多,所以我就重點談些別人一般忽略的部分吧.
BIOS Definitions
BIOS -- Basic Input and Output System,is used for initializing,testing and putting the PC into the ready state so that an OS may be started.Part of the BIOS remains in the system main memory after POST,or Power On Self Test.BIOS provides a consistent software interface to varying types of the hardware devices.It also provides the basic system level services to OS.The BIOS is also used for helping IHV to fix their hardware design bugs by using the SMM mode of the IA architecture.
上面這句話是我在初學BIOS的時候,我的老師,一位受到整個業界尊敬的杰出BIOS Engineer對我說的,這段話雖然短,但是卻清楚的道出了BIOS的基本功能,那就是:
(第一個)檢測硬體可能比較好理解一點,就是看看你的硬體是否還正常的工作,但是從軟體的角度看.其中最重要的就是對內存的檢測的.大家都還對剛開機的時候內存的大小一直在跳的螢幕有記憶吧,那就是在做Memory Test,或者說Memory Sizing.
(第二個)功能是初始化硬體,可能有不少朋友問:為什麼我的硬體還需要初始化?問的好,硬體的設計廠家往往為了通用市場的考慮,不願意將硬體設計成定制的狀態,可能一個網卡,可以安裝在PC,同樣也可以安裝在嵌入式系統上.所以為了使得硬體能夠按照PC的架構工作,BIOS必須要按照由IHV(Independent Hardware Vendor)提供的手冊將硬體設置好,比如寫几個必須的寄存器之類的,做一些enable的工作.這點非常重要,如果一個硬體沒有enable,那麼在OS下將不可見.
(第三個)功能是啟動操作系統,這也是BIOS必須要做的事情之一.啟動的方式是由BIOS規定,操作系統必須按照BIOS的要求來設計.這也是為什麼操作系統從DOS一直到Vista,都只能把自己的loader放在MBR,因為BIOS只讀MBR.強大的微軟都必須要按照這個不成標准的標准來:)當然,在EFI時代,這一點有所改變,EFI支持的Boot From File不在需要MBR.
(第四個)功能可能之前作過DOS開發的朋友比較熟悉吧,還記得INT 10基本螢幕服務,INT 13磁槃服務嗎?多少病毒正是靠INT 13來傳播.又有朋友曾經試圖繞過INT 10來直接寫螢幕?Windows時代,這些東西事實上仍然存在,並且繼續發揮着基本的核心作用,只是他們被Windows包裝起來了,一般的程序無法接觸到,但這並不能說明他們就沒有用處了.MS的開發人員不久前還表示,事實上甚至就是開發中的Longhorn的安裝程序,目前仍然有許多code是基於INT 10來寫螢幕的.
(第五個)功能估計一般的朋友可能就不知道了,就是之前稍微接觸過BIOS的朋友們可能也是第一次聽說吧!Intel在它的CPU裏專門留了個模式叫System Management Mode,擁有最高的權限.SMM中斷的時候,就連號稱無所不能的Windows的也不知道,這樣就可以給CPU補bug了,舉個例子,比如某天Intel的一個CPU對ADD指令給出錯誤操作結果,那麼就可以利用SMM在每次執行這個指令的時候,中斷一下,由BIOS軟體給出正確的執行結果.這就達到了給硬體修復缺陷的目的.這樣Intel也不用招回它的CPU了,呵呵.此外,每次BIOS開機的時候,事實上都會更新CPU Microcode,同樣是用來給CPU補bug的.所以很多時候,刷BIOS刷出問題,事實上某個CPU的bug沒有補上導致出了問題出現.
BIOS在哪裏
上面囉嗦了一大堆的BIOS Basics,那麼BIOS到底在哪里呢?答案是在你的計算機裏:) 的確有些無聊,事實上BIOS有三種狀態,分別是:
EFI BIOS
EFI是由Intel提出的,目的在於為下一代的BIOS開發樹立全新的框架。EFI是英文Extensible Firmware Interfaces的縮寫。正如它的名字一樣,EFI不是一個具體的軟體,而是在操作系統與平台固件(platform firmware)之間的一套完整的接口(interface)規範。EFI定義了許多重要的數據結構以及系統服務,如果完全實現了這些數據結構與系統服務,也就相當於實現了一個真正的BIOS核心。
EFI最早是在Spring 2000 IDF(Intel Developer’s Forum)上提出的,當時Intel認為,隨着IBM在80年代初推出了第一台個人計算機開始,直到今天為止,個人計算機硬體平台已經發生了翻天覆地的變化,相關的系統軟體如操作系統等也從最早的MS DOS1.0到今天的Windows XP,而作為整個系統的最底層也最為關鍵的系統軟體之一的BIOS卻基本上保持了架構二十年不變。這在整個軟體史上都是一件不可思議的事情。如今,BIOS已經變成了嚴重阻礙IT產業前進的絆腳石,必須通過對BIOS的革新來為下一代的操作系統(如Windows Server Longhorn)提供更加強大的支持。
上面是我很早之前寫的一段對EFI的介紹,現在看來,難免有些錯誤,不過大致意思非常明確,EFI就是用來替換傳統BIOS.作為更好的BIOS,EFI可以提供過去無法在BIOS中作到的許多事情.后面的文章我會逐步展現給大家.
一些常見的關于BIOS/EFI的問題以及我的簡短回答:
1) BIOS一般有多大?
傳統bios(以後說legacy bios)一般都是512KB,而早期的EFI bios也是512KB.現在EFI基本上是1MB了.
2) BIOS用什麼工具開發?
legacy bios一般用MASM 6.11開發,同時還會配上一些廠商自己寫的build tools. EFI則使用Visual Studio.NET 2003以及MASM 6.11開發(沒想到吧~)
3) EFI boot是怎麼一回事?
EFI有自己獨特的boot方式,完全拋棄掉了傳統的0磁道0扇區的MBR概念.EFI的boot方式與文件系統息息相關.過去的legacy bios由於不帶文件系統,不得已選擇從硬碟上特定空間裝載程序的辦法,而EFI則附帶了完整的文件系統支持,所以不再對硬碟有特定的要求,EFI下的操作系統加載程序事實上存儲在boot\ia32\bootia32.efi文件里.(假定是IA32架搆).這是一個EFI應用程序.
下面是一些深入學習bios的資源匯總:
1. BIOS Boot Specification
業內一般叫BBS,詳細描述bios啟動時必須要做的所有事情,如何區分啟動設備,如何選擇啟動設備等等.
http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf
2. UEFI Specification
UEFI規範,詳細描述了UEFI bios必須支持的接口.以及UEFI bios的模型,提供的服務等等. 開發UEFI必備的.
http://www.uefi.org
3. Ralf Brown's Interrupt List
這個人似乎就一輩子都都在收集中斷的東西,對legacy bios學習很有用.
http://www.ctyme.com/rbrown.htm
4. El Torito CD-ROM Boot 描述了bios如何從光碟上boot的細節.
http://www.phoenix.com/NR/rdonlyres/98D3219C-9CC9-4DF5-B496-A286D893E36A/0/specscdrom.pdf
5. USB Specification USB設備規範
http://www.usb.org
6. Plug-and-Play Specifications MS的PnP規範
http://www.microsoft.com/hwdev/tech/pnp/default.ASP
7. BIOS Writer's Guide
bios開發的聖經,由cpu廠商給出.Intel的絕對看不到,Intel的是絕密級的文檔.AMD的倒是可以看到,不同的cpu有不同的BWG.這里給出一個amd比較新的cpu的BWG:
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116.pdf
還有很多很多相關的文檔.其實編寫bios最難的在於同時支援業界幾乎所有的通用規範.
歡迎大家回帖提出相關問題. 我會在空閑時間一一作答.
轉載自:
http://www.huarw.com/program/assembler/assembler01/200804/1561026.html
小生不才,但也願意就我所學,貢獻成一篇簡短的入門文章,帶領大家進入BIOS這個有趣而又充滿了神秘的地域,我們一起來探究BIOS,尤其是探究下一代個人計算機的基礎系統軟體,或者說基礎固件:UEFI bios的方方面面.由于類似的文章網上也比較多,所以我就重點談些別人一般忽略的部分吧.
BIOS Definitions
BIOS -- Basic Input and Output System,is used for initializing,testing and putting the PC into the ready state so that an OS may be started.Part of the BIOS remains in the system main memory after POST,or Power On Self Test.BIOS provides a consistent software interface to varying types of the hardware devices.It also provides the basic system level services to OS.The BIOS is also used for helping IHV to fix their hardware design bugs by using the SMM mode of the IA architecture.
上面這句話是我在初學BIOS的時候,我的老師,一位受到整個業界尊敬的杰出BIOS Engineer對我說的,這段話雖然短,但是卻清楚的道出了BIOS的基本功能,那就是:
- 檢測硬體,又叫POST.
- 初始化硬體,設置其基本狀態,使得整個計算機達到所謂的"可用狀態"(Ready State).
- 啟動OS Loader加載操作系統.
- 在操作系統啟動起來以後,一部分繼續駐留內存(記憶體),向操作系統以及其他軟體提供基本的系統級的服務.如磁碟讀寫等.
- 修復硬體缺陷.
(第一個)檢測硬體可能比較好理解一點,就是看看你的硬體是否還正常的工作,但是從軟體的角度看.其中最重要的就是對內存的檢測的.大家都還對剛開機的時候內存的大小一直在跳的螢幕有記憶吧,那就是在做Memory Test,或者說Memory Sizing.
(第二個)功能是初始化硬體,可能有不少朋友問:為什麼我的硬體還需要初始化?問的好,硬體的設計廠家往往為了通用市場的考慮,不願意將硬體設計成定制的狀態,可能一個網卡,可以安裝在PC,同樣也可以安裝在嵌入式系統上.所以為了使得硬體能夠按照PC的架構工作,BIOS必須要按照由IHV(Independent Hardware Vendor)提供的手冊將硬體設置好,比如寫几個必須的寄存器之類的,做一些enable的工作.這點非常重要,如果一個硬體沒有enable,那麼在OS下將不可見.
(第三個)功能是啟動操作系統,這也是BIOS必須要做的事情之一.啟動的方式是由BIOS規定,操作系統必須按照BIOS的要求來設計.這也是為什麼操作系統從DOS一直到Vista,都只能把自己的loader放在MBR,因為BIOS只讀MBR.強大的微軟都必須要按照這個不成標准的標准來:)當然,在EFI時代,這一點有所改變,EFI支持的Boot From File不在需要MBR.
(第四個)功能可能之前作過DOS開發的朋友比較熟悉吧,還記得INT 10基本螢幕服務,INT 13磁槃服務嗎?多少病毒正是靠INT 13來傳播.又有朋友曾經試圖繞過INT 10來直接寫螢幕?Windows時代,這些東西事實上仍然存在,並且繼續發揮着基本的核心作用,只是他們被Windows包裝起來了,一般的程序無法接觸到,但這並不能說明他們就沒有用處了.MS的開發人員不久前還表示,事實上甚至就是開發中的Longhorn的安裝程序,目前仍然有許多code是基於INT 10來寫螢幕的.
(第五個)功能估計一般的朋友可能就不知道了,就是之前稍微接觸過BIOS的朋友們可能也是第一次聽說吧!Intel在它的CPU裏專門留了個模式叫System Management Mode,擁有最高的權限.SMM中斷的時候,就連號稱無所不能的Windows的也不知道,這樣就可以給CPU補bug了,舉個例子,比如某天Intel的一個CPU對ADD指令給出錯誤操作結果,那麼就可以利用SMM在每次執行這個指令的時候,中斷一下,由BIOS軟體給出正確的執行結果.這就達到了給硬體修復缺陷的目的.這樣Intel也不用招回它的CPU了,呵呵.此外,每次BIOS開機的時候,事實上都會更新CPU Microcode,同樣是用來給CPU補bug的.所以很多時候,刷BIOS刷出問題,事實上某個CPU的bug沒有補上導致出了問題出現.
BIOS在哪裏
上面囉嗦了一大堆的BIOS Basics,那麼BIOS到底在哪里呢?答案是在你的計算機裏:) 的確有些無聊,事實上BIOS有三種狀態,分別是:
- Before Build
- BIOS Image
- BIOS Runtime
EFI BIOS
EFI是由Intel提出的,目的在於為下一代的BIOS開發樹立全新的框架。EFI是英文Extensible Firmware Interfaces的縮寫。正如它的名字一樣,EFI不是一個具體的軟體,而是在操作系統與平台固件(platform firmware)之間的一套完整的接口(interface)規範。EFI定義了許多重要的數據結構以及系統服務,如果完全實現了這些數據結構與系統服務,也就相當於實現了一個真正的BIOS核心。
EFI最早是在Spring 2000 IDF(Intel Developer’s Forum)上提出的,當時Intel認為,隨着IBM在80年代初推出了第一台個人計算機開始,直到今天為止,個人計算機硬體平台已經發生了翻天覆地的變化,相關的系統軟體如操作系統等也從最早的MS DOS1.0到今天的Windows XP,而作為整個系統的最底層也最為關鍵的系統軟體之一的BIOS卻基本上保持了架構二十年不變。這在整個軟體史上都是一件不可思議的事情。如今,BIOS已經變成了嚴重阻礙IT產業前進的絆腳石,必須通過對BIOS的革新來為下一代的操作系統(如Windows Server Longhorn)提供更加強大的支持。
上面是我很早之前寫的一段對EFI的介紹,現在看來,難免有些錯誤,不過大致意思非常明確,EFI就是用來替換傳統BIOS.作為更好的BIOS,EFI可以提供過去無法在BIOS中作到的許多事情.后面的文章我會逐步展現給大家.
一些常見的關于BIOS/EFI的問題以及我的簡短回答:
傳統bios(以後說legacy bios)一般都是512KB,而早期的EFI bios也是512KB.現在EFI基本上是1MB了.
2) BIOS用什麼工具開發?
legacy bios一般用MASM 6.11開發,同時還會配上一些廠商自己寫的build tools. EFI則使用Visual Studio.NET 2003以及MASM 6.11開發(沒想到吧~)
3) EFI boot是怎麼一回事?
EFI有自己獨特的boot方式,完全拋棄掉了傳統的0磁道0扇區的MBR概念.EFI的boot方式與文件系統息息相關.過去的legacy bios由於不帶文件系統,不得已選擇從硬碟上特定空間裝載程序的辦法,而EFI則附帶了完整的文件系統支持,所以不再對硬碟有特定的要求,EFI下的操作系統加載程序事實上存儲在boot\ia32\bootia32.efi文件里.(假定是IA32架搆).這是一個EFI應用程序.
下面是一些深入學習bios的資源匯總:
1. BIOS Boot Specification
業內一般叫BBS,詳細描述bios啟動時必須要做的所有事情,如何區分啟動設備,如何選擇啟動設備等等.
http://www.phoenix.com/NR/rdonlyres/56E38DE2-3E6F-4743-835F-B4A53726ABED/0/specsbbs101.pdf
2. UEFI Specification
UEFI規範,詳細描述了UEFI bios必須支持的接口.以及UEFI bios的模型,提供的服務等等. 開發UEFI必備的.
http://www.uefi.org
3. Ralf Brown's Interrupt List
這個人似乎就一輩子都都在收集中斷的東西,對legacy bios學習很有用.
http://www.ctyme.com/rbrown.htm
4. El Torito CD-ROM Boot 描述了bios如何從光碟上boot的細節.
http://www.phoenix.com/NR/rdonlyres/98D3219C-9CC9-4DF5-B496-A286D893E36A/0/specscdrom.pdf
5. USB Specification USB設備規範
http://www.usb.org
6. Plug-and-Play Specifications MS的PnP規範
http://www.microsoft.com/hwdev/tech/pnp/default.ASP
7. BIOS Writer's Guide
bios開發的聖經,由cpu廠商給出.Intel的絕對看不到,Intel的是絕密級的文檔.AMD的倒是可以看到,不同的cpu有不同的BWG.這里給出一個amd比較新的cpu的BWG:
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116.pdf
還有很多很多相關的文檔.其實編寫bios最難的在於同時支援業界幾乎所有的通用規範.
歡迎大家回帖提出相關問題. 我會在空閑時間一一作答.
轉載自:
http://www.huarw.com/program/assembler/assembler01/200804/1561026.html
訂閱:
意見 (Atom)
-
昨天差點昏倒, 因為Chrome Browser一開啟後居然一片白畫面. 雖然還有IE可以用, 但就是習慣Chrome了啊, 然後開始Google別人如何解決, 不過看起來不少人遇到相同的問題, 但都沒什麼解決方法. 什麼掃毒啦, 重新安裝Chrome啦, 砍掉Default啦....
-
I/O mapped I/O(port-mapped I/O或Direct I/O) I/O與memory均擁有自己的記憶體空間 需要特別的指令來處理I/O 好處是完全不用考慮記憶體空間被I/O佔用,缺點需要額外的指令專門處理I/O存取。 Memory Mapped I/O I/...
-
Single cycle :Basicly one instruction one Cycle, and critical path more long. Multi cycle :one instruction many Cycle, buf critical path sho...
一個小故事讓我們明白資金流通的意義
“又是炎熱小鎮慵懶的一天。太陽高掛,街道無人,每個人都債台高築,靠信用度日。這時,從外地來了一位有錢的旅客,他進了一家旅館,拿出一張1000 元鈔票放在櫃檯,說想先看看房間,挑一間合適的過夜,就在此人上樓的時候---- 店主抓了這張1000 元鈔,跑到隔壁屠戶那裡支付了他欠的肉錢...