2009年4月21日 星期二

●memtest86+教學 Part11

圖二
圖一

我想在●memtest86+教學 Part9 中ㄉ介紹觀念還是很模糊,所以我貼出上面這張圖一及圖二,雖然我以visual PC 128MB作說明,但道理是一樣ㄉ。當然看這張圖必須參考memtest86+教學 Part6 中ㄉ圖PMAP-1。
--> 閱讀更多...

2009年4月19日 星期日

●基礎2-計算機表單設計

圖二
圖一

根據上圖一說明各物件name屬性:這些屬性可自己定義
數字按鈕1:Num_Button1
數字按鈕2:Num_Button2
‧‧‧
數字按鈕9:Num_Button9
數字按鈕0:Num_Button0
加法按鈕:add_btn
減法按鈕:sub_btn
乘法按鈕:mul_btn
除法按鈕:div_btn
清除按鈕:clear_btn
等號按鈕:equ_btn
square根號按鈕:square_btn
N階層按鈕:norder_btn
Hex按鈕:Hex_btn
Binary按鈕:Binary_btn
文字方塊:Display_Text
以下是部分代碼:
Private Sub Num_Button8_Click()
If (mode = 0) Then Num1 = Num1 + "8"
Display_Text = Num1 Else Num2 = Num2 + "8"
Display_Text = Num2
End IfEnd Sub

Private Sub Num_Button9_Click()
If (mode = 0) Then Num1 = Num1 + "9"
Display_Text = Num1 Else Num2 = Num2 + "9"
Display_Text = Num2
End IfEnd Sub

Private Sub square_btn_Click()
Display_Text = Str(Sqr(Val(Display_Text.Text)))
End Sub

Private Sub sub_btn_Click()
Display_Text = ""
mode = 2
End Sub

Private Sub UserForm_Initialize()
mode = 0
End Sub
我們依照上一篇ㄉ作法在EXCEL開啟時能夠馬上秀出這個計算機表單。實際作法由於我只列出部分程式碼,所以若有興趣您就下載去看看。我們在未來所用範例都是依照Office 2007,若您使用Office 2003,請自行修改成2003的格式。但是這個code,我故意留下N階層Binary沒作,就留給大家發揮一下。完成畫面如圖二。
--> 閱讀更多...

2009年4月15日 星期三

●memtest86+教學 Part10

圖一
上幾回我有提過memtest86+可以透過uart將畫面透過com port傳送到console;其畫面如圖一。今天我們先來介紹一些重要的變數:
struct vars variables = {};
struct vars * const v = &variables;
別小看這個"v",它運行於整個memtest86,可以說是核心資料結構;所以我們先從了解它著手:
struct vars {
int test; //目前所選取或正在測試中的pattern
int pass; //已經passㄉloop數
unsigned long *eadr; //沒用到,所以不知道宣告這ㄍ做什麼,真正用到ㄉ是在struct err_info erri裡面。
unsigned long exor; //同上
int msg_line; //要印出文字或數字ㄉ列數
int ecount; //錯誤數量
int ecc_ecount; //ecc錯誤數量,這應該也沒用到,因為我們不是測server dimm
int msegs; //從呼叫int 15h ax=e820h所得到ㄉ實體記憶體的segment數量
int testsel; //目前所選取ㄉpattern
int scroll_start; //看這個v->scroll_start = v->msg_line * 160;就知道意思
int rdtsc; //是否開始計時的變數(這ㄍ變數和assembly 指令一模一樣,不要搞混)
int pae; //判斷cpu是否支援分頁ㄉ變數
int pass_ticks; //目前的滴答數
int total_ticks; //總滴答數
int pptr; //顯示"#"總進度Progress的目前位置資訊
int tptr; //顯示"#"目前測試pattern進度Progress的目前位置資訊
int beepmode; //是否啟用pc喇叭
struct err_info erri; //這ㄍ結構底下會介紹
struct pmap pmap[MAX_MEM_SEGMENTS]; //以下4ㄍ這裡很難--
struct mmap map[MAX_MEM_SEGMENTS]; //用幾ㄍ字說清楚,--
ulong plim_lower; //我已另有--
ulong plim_upper; //文章說明。
ulong clks_msec; //CPU時脈
ulong starth; //開始計時ㄉ滴答數高32bits
ulong startl; //開始計時ㄉ滴答數低32bits
ulong snaph; //因為這ㄍ#undef TEST_TIMES所以沒用到此變數
ulong snapl; //因為這ㄍ#undef TEST_TIMES所以沒用到此變數
ulong extclock; //這也是CPU時脈,不知道為什麼要搞死大家
int printmode; //顯示fail的模式:預設值是PRINTMODE_ADDRESSES1
int numpatn; //當fail顯示模式為PRINTMODE_PATTERNS2時,要知道有幾個pattern fail
struct pair patn [BADRAM_MAXPATNS]; //還沒研究
ulong test_pages; //所插記憶體pmap總數
ulong selected_pages; //所插記憶體pmap總數(所以真ㄉ要搞死大家)
ulong reserved_pages; //type2及type4的pmap總數
};

struct err_info {
struct xadr low_addr;
struct xadr high_addr;
unsigned long ebits;
long tbits;
short min_bits;
short max_bits;
unsigned long maxl;
unsigned long eadr;
unsigned long exor;
unsigned long cor_err;
short hdr_flag;
};
以上這ㄍstruct在init.c中有初始化如下
v->erri.low_addr.page = 0x7fffffff;
v->erri.low_addr.offset = 0xfff;
v->erri.high_addr.page = 0;
v->erri.high_addr.offset = 0;
v->erri.min_bits = 32;
v->erri.max_bits = 0;
v->erri.min_bits = 32;
v->erri.max_bits = 0;
v->erri.maxl = 0;
v->erri.cor_err = 0;
v->erri.ebits = 0;
v->erri.hdr_flag = 0;
v->erri.tbits = 0;
當然要研究這ㄍstruct就是要搞懂error.c。
--> 閱讀更多...

●基礎1-EXCEL VBA初體驗

圖一
自定表單/工具箱
屬性視窗

專案視窗
我開使接觸VBA(visual basic application )是從office 2000開始,結果現在2009年office也release到office 2007,而且office也增加ㄌ更多的應用。但綜觀使用者的使用頻率,好像excel、word、power point、Access,才是大家最常用的。連linux也搞open office,但它好像不支援巨集(macro)功能,至少以前不支援,現在我就不知道ㄌ,雖然open office格式相容於MS Office但相容性有限。好ㄌ少說廢話,進入主題ㄅ,我又扯遠ㄌ。反正標題就是要說excel vba,其它就不講ㄌ:
首先學會如何開啟VBA功能,接著就來點簡單ㄉㄅ。以下我們所談內容都表示你已經開啟vba編輯視窗。要會VBA首先要認識專案視窗及屬性視窗;
專案視窗中:This Workbook指ㄉ就是你現在已經開啟ㄉexcel活頁簿,sheet1~sheet3指ㄉ就是活頁簿中的那三個工作表。專案視窗中左上角ㄉ按鈕(檢視程式碼)(檢視物件)便是切換編輯畫面的功能鍵。
今天我們先來和vba表單見個面ㄅ,因為我ㄉ習慣是若excel沒表單,那它就沒有讓我愛不釋手ㄉ理由ㄌ。在插入/自訂表單就會代出如上圖片。我們透過工具箱/Label,產生一個文字標籤,如上圖一,由屬性視窗我們知道,表單ㄉname屬性是UserForm1(可自行定義);接著我們今天來寫一行code如下。點選This Workbook,再點選(檢視程式碼),在程試碼編輯區上方有下拉視窗,目前應該顯示為"一般",改選為"Workbook";便會自動帶出兩行code如下,我在中間加入一行:
Private Sub Workbook_Open()
UserForm1.Show
End Sub
大功告成,儲存檔案。記得回excel(2007)設定開發人員/巨集安全性/巨集設定/啟用所有巨集。若是Excel(2003)則是工具/巨集/安全性/安全性層級/
如此你已完程第一個vba程式,並且會在這ㄍexcel檔開啟時也開啟那個表單視窗。
--> 閱讀更多...

2009年4月14日 星期二

●符合SMBIOS規範的電腦系統訊息獲取方法

以下這篇有關smbiosㄉ文章寫ㄉ很詳細,貼在自己ㄉ部落格是因為工作會常用到,怕說以後會找不到這份資料。
符合SMBIOS規範的電腦系統訊息獲取方法

作者:ramble(如需轉載請注明作者)
SMBIOS (System Management BIOS, SMBIOS),它是一種定出主機板及系統廠商如何以標準的格式顯示產品管理資訊的規格。SMBIOS 及 DMI(Desktop Management Interface)規格兩者皆是由 Desktop Management Task Force (DMTF) 所草擬的,它是一個由業界所領導,實行技術規格以確認開放性標準的組織。
對於符合SMBIOS規範的電腦,可以通過訪問SMBIOS的結構獲得系統訊息,共有兩種辦法可以訪問:
1.通過即插即用功能接口訪問SMBIOS結構,這個在SMBIOS2.0標准裏定義了,從SMBIOS2.1開始這個訪問方法不再被推薦使用。
2.基於表結構的方法,表内容是tableentry point的數據,這個訪問方法從SMBIOS2.1以後開始被使用,從2.1開始,以後的版本都推薦使用這種訪問方式。在2.1版本中允許支援這兩種方法中的任意一種和兩種都支援,但在2.2已經以後的版本,必須支援方法2。
鑒於市場上計算機已經均支援SMBIOS2.3標准,所以只考慮方法2,基於表結構的訪問方式。
基於表結構訪問SMBIOS的過程是先找到EntryPoint Structure(EPS)表,然後通過EntryPoint Structure(EPS)表的數據找到SMBIOS數據表。
訪問SMBIOSEPS表的操作過程如下:
1.從物理内存0xF0000-0xFFFFF間尋找關鍵字“_SM_”
2.找到後再向後16個字節,看後面5個BYTE是否是關鍵字“_DMI_”,如果是,EPS表即找到。
注:按照SMBIOS規範説明,找到關鍵字”_SM_”後就可以確定此處就是EPS表結構,但我在實際操作中發現有為數不少的電腦的指定64K内存中有不只一個“_SM_”,所以不能只用找到”_SM_”來確定,需要繼續判斷16個字節後是否是“_DMI_”。
SMBIOSEPS表結構如下:
位置 名稱 長度 描述
00H 關鍵字 4 byte 固定是“_SM_”
04H Check Sum 1 byte 用於檢查數據
05H 表結構長度 1 byte Entry Point Structure表的長度
06H Major版本號碼 1 byte 用於判斷SMBIOS版本
07H Minor版本號碼 1 byte 用於判斷SMBIOS版本
08H 表結構大小 2 byte 用於即插即用接口方法獲得數據表結構長度
0AH EPS修正 1 byte
0B-0FH 格式區域 5 byte 存放解釋EPS修正的訊息
10H 關鍵字 5 byte 固定為“_DMI_”
15H Check Sum 1 byte Intermediate Entry Point Structure(IEPS)的Check Sum
16H 數據表長度 2 byte SMBIOS數據表長度
18H 數據表位址 4 byte SMBIOS數據表的真實內存位置
1CH 數據表結構數目 2 byte SMBIOS數據表的結構數目
1EH SMBIOS BCD修正 1 byte
通過EPS表結構中的12H以及14H處(這裡說ㄉ應該是16h及18h,但我還是將原文呈現比較好),得出數據表長度和數據表地址,即可通過地址訪問結構表。從EPS表中的1CH處可得知結構表結構的總數,其中TYPE0結構就是BIOSinformation,TYPE1結構就是SYSTEMInformation。
每個結構的頭部是相同的,格式如下:
位置 名稱 長度 描述
00H Type number 1 byte 結構的type number
01H 長度 1 byte 本結的長度,就此type number的結構而言
02H Handle 2 byte 用於獲得SMBIOS結構,使用方法未知
每個結構都分為格式區域和字符串區域,格式區域就是一些本結構的信息,字符串區域是緊隨在格式區域後的一個區域。結構01H處標識的結構長度僅是格式區域的長度,字符串區域的長度是不固定的。
下面以TYPE0(BIOSinformation)為例説明格式區域和字符串區域的關系

TYPE0(BIOSinformation)格式區域如下:
位置 名稱 長度 描述
00H Type number 1 byte 結構的type number,此處是0
01H 長度 1 byte Type 0格式區域的長度,一般為14H,也有13H
02H Handle 2 byte 一般為0000H
04H BIOS廠商訊息 1 byte 此處是BIOS賣方的訊息,可能是OEM廠商名,一般為01H,代表緊隨格式區域後的字串區域的第一個字串
05H BIOS版本 1 byte BIOS版本號,一般為02H,代表字串區域的第二個字串
06H BIOS開始位址段 2 byte 用於計算常駐BIOS鏡像大小的計算,方法為(10000H-BIOS開始位址段)*16
08H BIOS發佈日期 1 byte 一般為04H,表示字串區第三個字串
09H BIOS ROM Size 1 byte 計算方法為(n+1)*64K,n為此處讀出的數值
0AH BIOS特徵 8 byte BIOS的功能支援特徵,如PCI,PCMCIA,FLASH等等
12H BIOS特徵擴展 不定
緊隨TYPE0(BIOSinformation)結構區域之後的就是TYPE0(BIOSinformation)字符串區域,如下所示:
db‘System BIOS Vendor Name’,0 ; 字符串以零結尾,第一個字符串:賣方訊息
db‘4.04’,0 ; 第二個:BIOS版本
db‘00/00/0000’,0 ; 第三個:發布日期
db0 ; 以0為整個字符區域的結尾,所以要找下一個TYPE,只要在字符區域找到連續的0000H即可
注:當有EPS表中得到結構表的開始地址後,可以直接按結構來尋找相應的TYPE號,找到後直接讀取就是該TYPE對應的結構的格式區域訊息,然後向後移動結構區域長度(結構區域長度由該結構的01H處讀出)個BYTE,即是該TYPE機構的字符串區域。
由上面介紹可知,獲得BIOS訊息的辦法就是:
1.通過EPS表的12H和14H數據找到TYPE結構表,然後找到TYPE0的内存地址。(不一定是首個)
2.由TYPE0結構區域中得出相應BIOS訊息是否存在(存在則是上面所述的 01H,02H,03H依次排布,不存在則是相應的位置上為00H)。
3.如存在訊息,則從字符串區域中讀取對應BIOS訊息。
獲得SYSTEM信息方法同上,只是TYPE結構區域有所不同,請參照SMBIOSReference Specification

在Linux環境裏可以使用dmidecode這支程式去dump SMBIOS的資料
dmidecode主要功能:
桌面管理介面提供標準化的電腦硬體描述,包括硬體的特性,比如 BIOS 的序號、與硬體連接線。dmidecode 提供由 BIOS 輸出 DMI 的資料,通常被其他硬體偵測程式當作後端工具使用。
轉載來源:
http://cupidsd.bokee.com/4052760.html\
其它參考資料:
System Management BIOS (SMBIOS) Specification
Desktop Management Interface (DMI) Standards
一篇世新的碩論-SMBIOS的研究與實作 寫得算蠻完整的唷
CodeGuru SMBIOS Demystified Windows VC++6.0
張貼者: 史丹利 位於 下午 9:05
--> 閱讀更多...

2009年4月9日 星期四

●有關32位元作業系統記憶體4G位址空間的局限

這篇文章網路有很多,但是對玩記憶體的我來說,卻不可不知。
有關32位元作業系統記憶體4G位址空間的局限:
4GB位址空間的局限:
首先我們還必須要先瞭解兩個概念
其一是“實體記憶體”。大家常說的實體記憶體就是指安裝在主板上的記憶體條,其實不然,在電腦的系統中,實體記憶體不僅包括裝在主板上的記憶體條(RAM),還應該包括主板BIOS晶片的ROM,顯卡上的顯存(RAM)和BIOS(ROM),以及各種PCI、PCI-E設備上的RAM和ROM。
其二是“位址空間”。位址空間就是對實體記憶體編碼(位址編碼)的範圍。
所謂編碼就是對每一個物理存儲單元(一個位元組)分配一個唯一的位址號 碼,這個過程又叫做“編址”或者“位址映射”。這個過程就好像在日常生活中我們給每家每戶分配一個位址門牌號。與編碼相對應的是“定址”過程——分配一個 位址號碼給一個存儲單元的目的是為了便於找到它,完成資料的讀寫,這就是“定址”,因此位址空間有時候又被稱作“定址空間”。系統不僅要給主板上的記憶體條 編址,還要給上述的其他實體記憶體編址;它們都被編在同一個位址空間內,編址後的實體記憶體就可以被系統資源使用或佔用。
從Pentium Pro處理器開始,CPU的 位址匯流排已經升級到36位元,定址能力達到64GB,按理說CPU支援4GB的記憶體是沒有問題的;因此,晶片組(北橋—MCH)位址匯流排的數量就成了決定物 理記憶體位址空間大小的決定性因素。在Intel 945系列和945以前的晶片組,nForce 550系列和550以前的晶片組都只有32條位址線,為系統提供4GB的位址空間,即最高可以安裝4GB的記憶體條。
雖然可以安裝4GB記憶體條,但這4GB的記憶體空間不能全部紛配給記憶體,因為從4GB空間的頂端位址(FFFF_FFFFh)開始向下要有400MB-1GB的位址空間要分配給主板上的其他實體記憶體。

我們可以看到4GB的位址空間可以分為兩大部分,0MB~實體記憶體頂端 的地址分配給主板上安裝的實體記憶體,4GB到實體記憶體頂端的位址分配給BIOS(ROM)和PCI/PCI-E設備的記憶體。由於這些記憶體基本上是用於 系統的輸入和輸出,所以Intel又把這段位址空間稱之為“MMIO”(Memory-Mapped I/O—I/O記憶體映射)。當系統安裝3GB以下的記憶體時,MMIO區域不會與實體記憶體條的位址空間相重疊,作業系統可以訪問幾乎全部的實體記憶體,而操 作系統屬性裏顯示的實體記憶體基本接近實際記憶體的容量。
而當系統安裝上4GB記憶體時,問題出現了。由於位於4GB下面的部分位址空間要優先分配給MMIO,記憶體條上對應的這段區間就得不到編址,所以作業系統就不能使用。
嚴格意義上來說,即使安裝2GB記憶體時作業系統也不可能使用到全部的內 存容量,諸如傳統DOS的UMA區就有部分被佔用的位址空間,但因為被佔用的容量相比之下實在太少,所以就被很多讀者忽略了。MMIO佔用的位址空間在 256MB~1GB之間,這麼大的“浪費”大家肯定不能“熟視無睹”。
因為受4GB晶片組位址空間的限制(32條位址線的限制),Intel 945系列及以前的晶片組、NVIDIA nForce 550及以前的晶片組都沒有辦法繞過這個限制。具體原因有三方面:其一是晶片組沒有剩餘空間分配來供作業系統來調配;其二是實體記憶體的編址必須是連續的, 不能被割斷;其三是系統開機時必需先從4GB的頂端位址(FFFF_FFFFh)讀取BIOS資料, 這是IA32架構和4GB位址空間的局限.
所以建議使用這些晶片組主板的用戶不要安裝4GB的記憶體,這樣會有部分記憶體容量不能被作業系統所使用。而解決4GB記憶體限制的唯一辦法就是擴展位址空間。

二、支援大於4GB記憶體的晶片組和“記憶體重映射”技術
面對原有晶片組4GB記憶體的局限,Intel和NVIDIA早就開始未雨綢繆,他們對傳統的32位元位址匯流排進行了 調整,將其升級到36位,並推出了一系列可以突破4GB記憶體限制的晶片組,這就是Intel的965系列以及975系列、NVIDIA的nForce 570/590以及680系列

注:AMD的64位元Socket AM2 CPU把記憶體控制器放到CPU中,提供40bit的物理位址匯流排,位址空間可達到1000GB。具體支援的位址空間和記憶體量取決於晶片組及主板的匯流排設計。
從上面的晶片組參數來看,位址匯流排從32位元提升到36位,位址空間達到 64GB,支持安裝8GB的實體記憶體。但由於IA32架構的規則是開機時必須從4GB的FFFF_FFFFh位址讀取BIOS資訊,儘管晶片組支援的位址 空間變大了,且最大支援的實體記憶體容量也達到了8GB(或以上),但從本質上來說仍然不能解決MMIO位址佔用4GB記憶體編址的問題。這要怎麼辦呢?
36位元位址匯流排最大可以支援64GB的位址空間,這就為移動MMIO地 址區提供了條件。現在解決這個問題的辦法就是“記憶體重映射”技術——就是在IA32架構的基礎上,把BIOS(ROM)和PCI/PCI-E設備佔用的 MMIO位址區段重新映射到記憶體條頂端位址以上 (例如4GB以上)的位址空間,從而把IA32架構規定的這一段作業系統不可使用的、位於4GB下面的MMIO位址空間回收給實體記憶體使用,保證實體記憶體 編址的連續性。

三、BIOS必須支援“記憶體重映射”
“記憶體重映射”技術必須通過BIOS完成。所以BIOS必須具有支援記憶體重映射的功能模組,以便根據用戶安裝的 記憶體容量來確定是否需要啟用記憶體重映射功能。同時,在BIOS的設置選單中也要有“Memory Re-Mapping”的設置選項,使用4GB或者4GB以上記憶體的用戶一定要將此項設置設為“Enable”。

四、解決4GB記憶體問題還需要作業系統支援
我們常使用的桌面作業系統是32位元的,支援4GB的位址空間。前面我們介紹了解決4GB問題的晶片組是支持 64GB位址空間的,在這樣的晶片組主板上安裝32位元的作業系統,就只能使用4GB的位址空間,因此安裝4GB記憶體不能使用僅支援4GB位址空間的32位元 的作業系統。應該使用支援大於4GB位址空間的32位元作業系統或64位元的作業系統。

五、小結.
1、由於iA32架構要求BIOS(ROM)晶片的位址, PCI、PCI-E記憶體位址、APCI中斷路由位址等必須佔用從4GB開始以下的256M-1GB空間。這段MMIO位址區不能分配給記憶體條。4GB的記憶體條有256MB-1GB的容量不能編址而浪費。
2、使用4GB或者以上的記憶體條,必須使用位址(編址)空間64GB的晶片組主板。
3、記憶體重映射就是把被MMIO佔用的位址移到記憶體條容量以上的位址空間。)
4、BIOS應具有支援“記憶體重映射”功能,設置項裏有 Memory Remap Feature 選項,並設置為Enable。
5、必須安裝定址空間大於4GB的作業系統。比如Windows 2000高級伺服器版,以及64位元作業系統。
6、所有位址空間為4GB的晶片組(Intel945和nForce550之前的),和32位元作業系統均不能利用“記憶體重映射”技術解決4GB記憶體問題。

跟這有關ㄉ討論還有這ㄍ連結
--> 閱讀更多...

2009年4月6日 星期一

●memtest86+教學 Part9





今天我們要談mem_size();這ㄍroutine;還記得上一章我們已經呼叫完int 15h ax=e820h;接下來我們介紹2ㄍstruct:來將我們呼叫15h中斷所得到ㄉ資料儲存到這裡來
struct mem_info_t {
unsigned long e88_mem_k; /* 0x00呼叫int15h時 eax=e88h,結果存放於此 */
unsigned long e801_mem_k; /* 0x04呼叫int15h時 eax=e801h,結果存放於此 */
unsigned long e820_nr; /* 0x08呼叫int15h時 eax=e820h,e820map總數存放於此 */
struct e820entry e820[E820MAX]; /* 0x0c 開始存放以20bytes為單位的e820 的structure*/
/* 0x28c此address是最多32個structure的end位址 */
};
struct e820entry {
/*此結構專門用來存放呼叫int15h時 eax=e820h時所得到的資訊,以便以c語言來處理這些資料*/
unsigned long long addr; /* start of memory segment long long是8個bytes */
unsigned long long size; /* size of memory segment long long是8個bytes */
unsigned long type; /* type of memory segment long是4個bytes 以上便是一個20byte的資料結構*/
};
主程序呼叫子程序以後以”=>”這個符號來表示呼叫由以上兩個structure來說明下面的程式架構: Init()=>query_pcbios()因此進入head.S並且切換cpu進入real mode,執行int15h中斷eax=e820h,因此獲得
memory map數量,最多32個,其實只有3個到5個;依照你所插入ㄉ記憶體容量及各家主機板BIOS實作方法不同而定。接著Init()=>mem_size()並將memory map配置給e820entry。 然後mem_size()=>memsize_bios(0)=>memsize_820(0)=>sanitize_e820_map(e820, nm, e820_nr, res)。
sanitize_e820_map就是整理所有memory map的routine(他(這ㄍROUTINE)比較繁雜,我都看不下去)。在此先說明memsize_bios(),它只是去判斷我們是透過什麼方式取得memory map,我們都知道目前應該都會是query_pcbios()來取得,所以代入參數0。
至於memsize_820(res)也是代入0為參數,那麼此routine做了些什麼,我們來看看:

static void memsize_820(int res) {
int i, n, nr;
struct e820entry nm[E820MAX];

/* Clean up, adjust and copy the BIOS-supplied E820-map. */
/* If the res arg is true reclassify reserved memory as E820_RAM */
nr = sanitize_e820_map(e820, nm, e820_nr, res);

/* If there is not a good 820 map use the BIOS 801/88 info */
if (nr <> E820MAX) {
memsize_801();
return;
}
/* Build the memory map for testing */
n = 0;
for ( i=0 ; ( i < nr ) ; i++ ) { if (nm[i].type == E820_RAM) { unsigned long long start; unsigned long long end; start = nm[i].addr; end = start + nm[i].size;
/* Don't ever use memory between 640 and 1024k */
if (start > RES_START && start < RES_END){
if (end < RES_END){
continue;
}
start = RES_END;
}
if ( end > RES_START && end < RES_END){
end = RES_START;
}

此顏色區域目的是要避開640k~1024k因此只要任何memory map 有涵蓋此區域其start或end就會被設定到640k為end或設定1024k 為start。(這部分是dos作業系統及bios專用空間,當然也包括我們程式要做顯示畫面0xb8000到0xb8fff這塊記憶體,所以這裡測試程式永遠都不會來測這一小塊。)
v->pmap[n].start = (start + 4095) >> 12;
v->pmap[n].end = end >> 12;
v->test_pages += v->pmap[n].end - v->pmap[n].start;
n++;
/*pmap+0xfff(4095)只是作4k為單位前的無條件進位。*/

/*v->pmap[n].end - v->pmap[n].start//便是求算出以4k為單位的總頁數。*/
}
else {
/* If this is reserved memory starting at the top
* of memory then don't count it as reserved, since
* it is very unlikely to be real memory.
*/
if (nm[i].addr <>reserved_pages += nm[i].size >> 12 }
}
v->msegs = n;
if (res) { cprint(LINE_INFO, COL_MMAP, "e820-All"); }
else { cprint(LINE_INFO, COL_MMAP, "e820-Std"); } }
●以上程式碼要看n平方次才會懂ㄉ,尤其是那ㄍ
sanitize_e820_map
--> 閱讀更多...

2009年4月5日 星期日

●Linux ubuntu簡介


由於從前安裝linux都是使用一棵hd,安裝多作業系統的方式,但是每次要到其他os工作就必須reboot;這樣其實對我ㄍ人來說極為不便;更何況自從有ㄌvmware及virtual PC或Sun virtual Box我個人就不再玩多作業系統於單一hd。而且還有samba 支援,做起事來可以在單機游走於windows及linux,真是快活。
linux:當然Fedora及Red_hat都不錯,但我想debian更多人用ㄅ。ubuntu也是源自於debian。

首先我還是說一下版本問題及喜好:ubuntu-8.10-desktop-i386.iso、ubuntu-8.10-alternate-i386.iso,若你想安裝最新版ubuntu 9.04應該快ㄌ,現在只有beta版,所有我還是,建議使用8.10版。ubuntu-8.10-desktop-i386.iso這ㄍ安裝是圖形介面所以建議虛擬機器至少配置512mbㄉ記憶體;安裝過程可能會有些螢幕小問題要解決如下。ubuntu-8.10-alternate-i386.iso這是installs on systems with less than about 256MB of RAM版很好用,虛擬機器至少配置256mb跑起來就很好很順ㄌ。

Desktop版本我使用virtial pc及Sun xVM virtualBox安裝都沒問題。安裝完若覺得螢幕解析度不符合您ㄉ須求可透過以下設定:上圖是我在(桌機)安裝好ㄉ圖例(我nb是裝virtual pc一樣沒問題)。若您安裝ㄉ板本較舊(7.04或7.10或8.04)可能相對問題會增加。至於音效說明請往下看#vim /etc/X11/xorg.conf

Section “Device”Identifier “Configured Video Device”
Driver “vesa”
Option “UseFBDev” “true”
EndSection

Section “Monitor”
Identifier “Configured Monitor”
Option “DPMS”
HorizSync 30-70
VertRefresh 50-160

EndSection

Section “Screen”
Identifier “Default Screen”
Monitor “Configured Monitor”
Device “Configured Video Device”
DefaultDepth 16
SubSection “Display”
Depth 16
Modes "1280×1024" "1024×768" "800×600"
EndSubSection

EndSection


--> 閱讀更多...

2009年4月2日 星期四

●memtest86+教學 Part8

static void display_init(void)
{
int i;
volatile char *pp;
/*只要是印出資料一定會宣告這個指標,volatile表示可變ㄉ,若不加沒事,但compile可能會發出警告。*/

serial_echo_init();
serial_echo_print("\x1B[LINE_SCROLL;24r"); /* Set scroll area row 7-23 */
serial_echo_print("\x1B[H\x1B[2J"); /* Clear Screen */
serial_echo_print("\x1B[37m\x1B[44m");
serial_echo_print("\x1B[0m");
serial_echo_print("\x1B[37m\x1B[44m");
/*以上6行是com port的輸出到(uart),若你在config.h將#define SERIAL_CONSOLE_DEFAULT 0改成1,並接上跳線,從你的os開起一個console 並設好鮑率,你就會接收看到一ㄍ長像和memtest一樣ㄉ單色畫面,聰明的你應該就知道上面那些長像奇特ㄉ鳥東西一定是字元控制碼,可能和uart輸出位置或什麼有關,但是很sorry,我也找不到這些控制字元的specifiction,若是你有,煩請mail一份給我。反正現在重點不是這ㄍ,只要遇到serial_echo_print你可以先不理他*/
for(i=0, pp=(char *)(SCREEN_ADR); i lss 80*24; i++) { *pp++ = ' '; *pp++ = 0x17; } /* 以上是清除畫面;0x17是藍底白色字屬性;但印出空白所以看不到白色字 */ /* Determine the memory map */ if ((firmware == FIRMWARE_UNKNOWN) && (memsz_mode != SZ_MODE_PROBE)) { if (query_linuxbios()) {
/*linuxbios目前support這種架構ㄉ主機板雖不多,但會不會成為主流也不知道,畢竟memtest是GPL,所以一定會挺同門師兄弟,將這個routine加進來。但畢竟所有主機板目前還是會支援正統ㄉbios,所以這ㄍroutine呼叫失敗也沒關係,下面那ㄍquery_pcbios一定會成功;什麼,不成功會怎樣,就什麼都別玩了,關機去休息吧。*/
firmware = FIRMWARE_LINUXBIOS;
}
else if (query_pcbios()) {
firmware = FIRMWARE_PCBIOS;
}
}
/*query_pcbios()你不會要問我這ㄍroutine在哪裡ㄅ;在爛豬腳裡;所以豬腳飯才那麼好吃;但是你會想我們不是好不容易才走出組合語言的陰影ㄇ,現在又要進去"拉d賽",沒辦法誰叫它的名字叫"X86",因為我們要去呼叫int 15h,但是中斷偏偏又只能在真實模式,所以只好又要重新出、進保護模式*/
.globl query_pcbios//匯出到符號表;這是一定要ㄉ,否則C呼叫不到Assembly的函式
query_pcbios:
‧‧‧
‧‧中間這一段我之前也trace很辛苦,所以先不說,
‧但不是我喜歡藏功夫,而是又一言難盡。改天再續‧‧

/* switch to 16bit mode */切到真實模式
ljmp $REAL_CS, $1f - RSTART
1:
.code16
/* Disable Paging and protected mode */
/* clear the PG & PE bits of CR0 */
movl %cr0,%eax
andl $~((1 SHL 31)(1 SHL 0)),%eax #關閉分頁及保護模式,回到真實模式
#Try three different memory detection schemes. First, try
# e820h, which lets us assemble a memory map, then try e801h,
# which returns a 32-bit memory size, and finally 88h, which
# returns 0-64m

# method E820H:
# the memory map from hell. e820h returns memory classified into
# a whole bunch of different types, and allows memory holes and
# everything. We scan through this memory map and build a list
# of the first 32 memory areas, which we return at [E820MAP].
# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
取得記憶體的分佈圖,以上介紹ㄉ是ax=e820h,int 15h中斷和e801h88h,由於歷史因素,記憶體在系統啟動後分佈並不是連續性的,因此我們必須非常確定它ㄉ分佈狀況,下面ㄉ代碼便是實作這三種方法。而且後兩者是較舊的主機板不支援e820時ㄉ應變之道,況且這些機種早就沒人用ㄌ,多舊?486ㄅ及更早;所以主流一定會support e820h,你放心。下面ㄉcode e820h 網路上一定找ㄉ到說明。我就不說,什麼,小氣;再說又要叫你買書ㄌ,我又不是"37仔"。
meme820:
xorl %ebx, %ebx # continuation counter
movw $E820MAP, %di # point into the whitelist
# so we can have the bios
# directly write into it.

jmpe820:
movl $0x0000e820, %eax # e820, upper word zeroed
movl $SMAP, %edx # ascii 'SMAP'
movl $20, %ecx # size of the e820rec
pushw %ds # data record.
popw %es
int $0x15 # make the call
jc bail820 # fall to e801 if it fails

cmpl $SMAP, %eax # check the return is `SMAP'
jne bail820 # fall to e801 if it fails

# cmpl $1, 16(%di) # is this usable memory?
# jne again820

# If this is usable memory, we save it by simply advancing %di by
# sizeof(e820rec).
#
good820:
movb (E820NR), %al # up to 32 entries
cmpb $E820MAX, %al
jnl bail820

incb (E820NR)
movw %di, %ax
addw $E820ENTRY_SIZE, %ax
movw %ax, %di
again820:
cmpl $0, %ebx # check to see if
jne jmpe820 # %ebx is set to EOF
bail820:


# method E801H:
# memory size is in 1k chunksizes, to avoid confusing loadlin.
# we store the 0xe801 memory size in a completely different place,
# because it will most likely be longer than 16 bits.

meme801:
stc # fix to work around buggy
xorw %cx,%cx # BIOSes which dont clear/set
xorw %dx,%dx # carry on pass/error of
# e801h memory size call
# or merely pass cx,dx though
# without changing them.
movw $0xe801, %ax
int $0x15
jc mem88

cmpw $0x0, %cx # Kludge to handle BIOSes
jne e801usecxdx # which report their extended
cmpw $0x0, %dx # memory in AX/BX rather than
jne e801usecxdx # CX/DX. The spec I have read
movw %ax, %cx # seems to indicate AX/BX
movw %bx, %dx # are more reasonable anyway...

e801usecxdx:
andl $0xffff, %edx # clear sign extend
shll $6, %edx # and go from 64k to 1k chunks
movl %edx, (E801) # store extended memory size
andl $0xffff, %ecx # clear sign extend
addl %ecx, (E801) # and add lower memory into
# total size.

# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
# 64mb, depending on the bios) in ax.
mem88:

movb $0x88, %ah
int $0x15
movw %ax, (E88)

#ifdef APM_OFF
# check for APM BIOS
movw $0x5300, %ax # APM BIOS installation check
xorw %bx, %bx
int $0x15
jc done_apm_bios # error -> no APM BIOS

cmpw $0x504d, %bx # check for "PM" signature
jne done_apm_bios # no signature -> no APM BIOS

movw $0x5304, %ax # Disconnect first just in case
xorw %bx, %bx
int $0x15 # ignore return code

movw $0x5301, %ax # Real Mode connect
xorw %bx, %bx
int $0x15
jc done_apm_bios # error

movw $0x5308, %ax # Disable APM
mov $0xffff, %bx
xorw %cx, %cx
int $0x15

done_apm_bios:
#endif
‧‧‧
‧‧

/* Turn on protected mode */切回保護模式
/* Set the PE bit in CR0 */
movl %cr0,%eax
orl $(1 shl 0),%eax #回到保護模式
movl %eax,%cr0
data32 ljmp *(protptr - RSTART)/*跳到下一行的32bits code繼續執行。這種語法未來會介紹。*/
prot:
.code32
/* Reload other segment registers */
movl $KERNEL_DS, %eax /*32bits code*/
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %eax, %ss

/* Adjust the stack pointer */
leal stack@GOTOFF(%ebx), %eax
addl %eax, %esp

/* Restore the caller saved registers */
popl %ebp
popl %edi
popl %esi
popl %ebx
movl $1, %eax
ret //query_pcbios()到此結束
這ㄍret就是query_pcbios()ㄉ返回,你看它反回前作ㄌ一件事,就是eax設為1,所以,以下這ㄍif條件成立,因為c編譯器預設就是將eax當成return code。
else if (query_pcbios()) {
firmware = FIRMWARE_PCBIOS;
}
待續‧‧‧
--> 閱讀更多...

2009年4月1日 星期三

●老是記不住ㄉ指令


P.S.:上圖是給使用vim及viㄉ使用者一ㄍ很好記指令ㄉ圖檔。你也可以將它印出來隨時用隨時查。
在virtual PC安裝ubuntu linux text mode,由於要讓samba啟用必須作一些設定,其實很簡單,只要確定安裝linux時有選取samba,因此進入ubuntu之後盡可能不要用root身份來操作。
1新增使用者:指令adduser
EX:adduser -a 名稱
2修改user為root權限:需修改/etc/sudoers這ㄍ檔案
3設定samba指令:smbpasswd -a 名稱
並修改/etc/samba/smb.conf
4修改電腦名稱:要改2ㄍ地方,/etc/hostname及/etc/hosts
5(非必要)另外若同一網段MAC ADDR衝突也必須作設定:
/etc/udev/rules.d/70-persistent-net.rules
6(非必要)鎖住或關閉其他用戶ㄉ指令:passwd -L 名稱

以root身份執行工作,所以必須切換為rootㄉ指令:sudo -i

tar壓縮/解壓縮指令如下
檔案格式 壓縮 解壓縮 範例
bz2 -cjf -xjf tar -xjf xxx.bz2
gz -czf -xzf tar -xzf xxx.gz
選項與參數說明:指令說明是參考鳥哥的私房菜
-c:建立打包檔案,可搭配 -v 來察看過程中被打包的檔名(filename)。
-t:察看打包檔案的內容含有哪些檔名,重點在察看『檔名』就是了;
-x:解打包或解壓縮的功能,可以搭配 -C (大寫) 在特定目錄解開特別留意的是, -c, -t, -x 不可同時出現在一串指令列中。
-j:透過 bzip2 的支援進行壓縮/解壓縮:此時檔名最好為 *.tar.bz2-z :透過 gzip 的支援進行壓縮/解壓縮:此時檔名最好為 *.tar.gz。
-v:在壓縮/解壓縮的過程中,將正在處理的檔名顯示出來!
-f filename:-f 後面要立刻接要被處理的檔名!建議 -f 單獨寫一個選項!
-C 目錄:這個選項用在解壓縮,若要在特定目錄解壓縮,可以使用這個選項。
其他後續練習會使用到的選項介紹
-p :保留備份資料的原本權限與屬性,常用於備份(-c)重要的設定檔。
-P :保留絕對路徑,亦即允許備份資料中含有根目錄存在之意。
--exclude=FILE:在壓縮的過程中,不要將 FILE 打包!

/*****************************************************/

/************* SecureCRT Serial com port設定*************/

/*****************************************************/
Session Option:
Serial/Flow Control:RTS/CTS
Modes:initial mode:new line mode 及Application krypad
current mode:和initial mode一樣

Global Option:預設值
--> 閱讀更多...