小華的部落格: NVRAM list v.s NVStore

搜尋此網誌

網頁

星期四, 6月 19, 2008

NVRAM list v.s NVStore

最近接了一個新的案子,雖然還沒開始Run但是事前的準備也不能少,也因此遇到了新問題,所以在部落格留下紀錄以後好方便查詢!

在跟客戶接觸的過程中,他們要求我提供CMOS NVRAM List ,用過P公司的BIOS的人都知道, P公司會產生這個List ,而這個List其實就是對應我們在Setup Menu中的選項設定值(例如某個item內有Enable/Disable選項而選擇後的值會存放進去CMOS當中) ,有了這份List ,客戶就可以開發自己的工廠測試程式去修改CMOS內的設定值來達到他們的需求(不考慮Checksum問題時可以這樣做)。最常見的就是修改Boot Order (修改開機順序),當然這些工具還是需要BIOS端的支援啦!

而我的問題在於EFI架構中為了一些安全性的考量,已經建議這些設定值的存放地方改至NVStore,即直接寫入至BIOS ROM中的某個規劃出來的區塊,因此我沒辦法直接修改CMOS來達到修改某個item的設定值,除非你在POST的BIOS code中去讀取你自己定義的CMOS位置然後在去改變他,這部分我們學長已經是這樣子的方式來修改BootOrder!


方式一:
AP修改CMOS --> POST過程中BIOS去讀取CMOS值 -->BIOS修改至相關Variable位置

有關於NVStore部分,在不同的bios廠商中做法也是不見得會完全依照當初的建議去做,像是P公司現階段的BIOS code就比較尷尬...因為他不是完全的EFI 架構,所以有一部分還是存放在NVRAM 中 ,一部分是存放在NVStore ,所以在過度期中他還是有提供NVRAM list,只可惜這次的案子不是使用p公司的BIOS =.=!

路不通就自己通, 因此在EFI 架構下我自己寫了一個介面給AP端使用(修改cmos在由POST 開機時讀取出來修改的方式我學長已經實做成功,所以我才試試看改寫另一種方式),方式是透過SW SMI Driver來註冊一個SMI Routine ,然後在這個Routne中去得到AP端傳進來的RAM Buffer,而這塊RAM Buffer中說明了我要去修改/讀取哪一個NV Variable 以及要寫入/回傳的資料 ,因此在DOS或是Windows下就可以很方便的透過這個介面去修改設定值。

而ap端我是採用TC++ 3.0 先去配置一塊記憶體,然後把參數寫進去這塊記憶體,然後用ESI指向這塊記憶體,接著發送SW SMI ,如下面所示

type struct {
DWORD Protocol; (Byte/word/dword)
DWORD VarIndex;
DWORD VarData;
}OEM_BUFFER

STATUS OEM_SMI_Trigger(OEM_BUFFER *inputbuf,OEM_BUFFER *outputbuf)
{
AH=Select Fun (Read/Write)
AL=SW SMI function number
ESI=input buffer
EDI=output buffer
EBX = Signature '$OEM'
DX=B2h
}

方式二:
AP端將參數寫至RAM --> AP端設定好暫存器,指向存放參數的RAM --> AP端觸發SMI --> BIOS透過暫存器得到參數 --> BIOS SMM code設定相關Variable.


結論:
透過方式一的方式簡單又方便,但是缺點在於傳遞的資料量有限,且如果變數過多時會很麻煩!

透過方式二的方式複雜但是可以傳遞較大的資料量,應用也比較廣,變數過多也無所謂,因為BIOS端會把這些item都集中然後放在某個Structure中,所以只要指定好Index就可以了(以前叫做Token),其他應用可以類似寫一個燒BIOS ROM的介面,透過BIOS本身的Code去燒...目前某家EFI BIOS公司就是這樣子去開發Flash utility...

21 則留言:

匿名 提到...

想請教一下
您說P公司會產生這個List
是在build後產生出來的?那是放在哪呢?

我是用組語的code...

小華的部落格 提到...

OEM.tip

匿名 提到...

在Dual code系統下,如果是Windows底下的AP來發SW SMI傳參數,還要判斷哪個CPU

小華的部落格 提到...

嗯嗯, 我的做法是做一個for迴圈(i=0 to NumberofProcessor),然後在SMRAM記憶體中檢查我自已定義的'$OEM'標記(放在EBX)

匿名 提到...

如果AP不是你自己寫的, 不能自已定義的'$OEM'標記(放在EBX),怎麼辦?

小華的部落格 提到...

在我的部份我只要把BIOS端的介面做好,其他人只要遵循規則就可以了,因為這個功能是屬於我所提供的BIOS端介面,所以就算AP不是自己寫的也沒關係,因為想要寫的人自己去遵循我定的規範就好了啊!

另外我會使用標記'$OEM'就是為了防止其他人不小心呼叫到這個SMI Routine,另外還可以方便我去找到負責的CPU.

至於想寫AP但是又不會把'$OEM'放到EBX的人我也可以提供Sample code給他,因為我自己在實做這個功能時就已經把AP也順便寫好了,所以並不是太大的問題啦!

匿名 提到...

你可能會有機會遇到AP是別人寫的,你要去配合他,而且沒有$OEM

小華的部落格 提到...

恩,是有機會遇到! 不過這跟我自己寫介面給別人用是不一樣的事情! 因為這是我定的規範,所以我要強調,如何做是要看我的bios端如何去寫出這個介面並定義規範出來給寫AP的人去遵循 ,而您提的是別人定規範給我做,所以是不一樣的!

針對你說的情況是別人的AP需要某些功能,而這部分需要BIOS支援,當遇到這種情況的時候我是建議您要跟寫AP的人坐下來談!因為是合作關係,所以大家能彼此合作才是重點.

如果寫AP的人不願意配合BIOS也不願意協商最佳解決方案,又喜歡命令BIOS去做東做西的,那麼就請寫AP的人自己想辦法吧! 如果真的那麼有能力就請他別找BIOS 幫忙開後門吧!

匿名 提到...

Dear 小華:

Nice to meet you,
I have some info can give you and hope you can share them to everybody, you can msn me
chenhy88tw@hotmail.com or visit my blog chen-hy.blogspot.com, thanks!

Regards,
HY

匿名 提到...

(因為他不是完全的EFI 架構,所以有一部分還是存放在NVRAM 中 ,一部分是存放在NVStore)
EFI所存放的NVRAM不就是ROM所切出的一塊區域嗎?跟NVStore有什麼不同?

小華的部落格 提到...

>EFI所存放的NVRAM不就是ROM所切出的一
>塊區域嗎?跟NVStore有什麼不同?

我的講法可能有一些語病..我把我的定義解釋一下:

NVRAM - CMOS / ROM ,我喜歡看作CMOS
NVStore - 為了跟CMOS區分,所以我喜歡把ROM那塊稱為NVStore

所以字面上的意思讓你混淆了,不好意思喔 >.<

小華的部落格 提到...

題外話:因為我是先學P廠商的Legacy BIOS,後來才學EFI BIOS的,所以習慣稱:

NVRAM = CMOS

但是在"純"EFI 架構中,NVRAM幾乎都是指ROM的那ㄧ塊,所以我才喜歡這樣分,不過目前P廠商還不夠"純",所以才會有這樣的過度期..(CMOS & ROM 同時都有)

[Note] 其實在"純" EFI 的廠商中,也是會偷用CMOS啦...

匿名 提到...

感謝您的回覆
對於EFI的CMOS NVRAM
再延伸一個問題
傳統的Legacy Bios我們利用Pin腳Clear Cmos就可以將值清成預設值
這樣的話我們在EFI底下做這個動作
存在NVRAM的值不就都不會改變?
或者在Code當作要動這個手腳
假設Pin被Clear就將NVRAM清掉
還是在EFI Spec當作沒有清NVRAM這回事?
Thx

小華的部落格 提到...

cmos - 一樣可以用你講的pin去清除

EFI NVRAM - 你就想成他是類似Legacy BIOS的ESCD區塊,那你能用某支pin去清除那一塊的資料嗎?

但是如果你真的要做的話應該也是做得到,可是有個限制就是:

BIOS需在POST過程中去"辨識某些條件(某支GPIO or ..)",然後自己回復預設值

其他我所知道的就是BIOS每次都會去檢查"Variable checksum or header"是否正確,如果有問題就會自己回復預設值,所以當"燒進去BIOS的Var有問題時",某些BIOS廠商會有緊急修復機制來修復這些資訊..

以我目前知道的知識就是這些,希望對你有幫助!

匿名 提到...

就我所知
當我安裝了EFI Aware OS(EX:Vista 64bit SP1)之後
OS會在NVRAM存一個Variable
也就是這個OS Boot的路徑
如果這個路徑不見了
Aware的OS就會開不起來
這樣未來可能會有一個問題產生
當使用者灌EFI Aware OS
又清除了NVRAM(路徑被清掉)
那他的OS就開不起來了
是這樣嗎?在清NVRAM時需要注意這個路經嗎?
THX

小華的部落格 提到...

>>"OS會在NVRAM存一個Variable"

你說的這部分我還沒接觸過,之前K EFI Spec時好像有看到這部份的描述不過我還沒仔細看,我印象中記得是有個Variable存放OS Boot path,但是是否是OS去存的我就不確定了!

EFI架構中是可以由OS端去呼叫BIOS的相關Services來執行,不過我沒有實作過,聽人家說是先去找到BIOS 的SystemTable,然後再去呼叫Routine,但是我目前接觸的都還是LegacyOS ,所以沒辦法給你任何建議..

而如果是Variable,就會被存放在BIOS劃分出來的區塊,清除整塊時當然是整個清,但是你可以在清除前先備分你說的OS Boot path,清完後再回寫不是嗎?

匿名 提到...

的確是能在清完後寫回
我好奇的部份是
為什麼EFI要有一個boot的路徑在NVRAM
是不是表示EFI沒有清NVRAM的機制
因為一旦清掉路徑也會消失

sunil 提到...

因為efi boot的時後,會去load 一個bootmgfw.efi 的OS loader
那個path 就是指到這個file~~
如果NVRAM被清掉的話~~在bios 選單裡應該有個選項~~add new bootpath ??
類似的~~選項~~
可以把那個path再加回去

匿名 提到...

我是從 OS level 角度來看這個問題, 提出下列的做法:

1. 寫 Parser 來解譯 CMOS NVRAM List, 轉成我方自訂的 NVStore 格式.

2. Base on parser, 寫個 Window 版的 Editor. 讓 user 以操作傳統
BIOS Menu 設定的方式, 輸入出廠預設值後, 直接轉成 NVStore File.

3. Bind the NVStore File into BIOS, and flash into EEPROM.

4. 若還有時間, 乾脆寫個 Window 版的 BIOS Setup Menu.
來支援多國語言, 外加 Help 檔解釋每個 Setting Option 的含意.

我想 Phoenix 是家大公司, 應該有定義 1 套嚴謹的 CMOS NVRAM List Spec.
能弄到這套 Spec, Parser 就好寫多了, 也不怕有格式不相容的問題.

寫出個簡單易用的 editor, 讓高職小妹妹都會操做, 都能套到所有用
Phoenix BIOS 的機器上, 如此可大幅降低人力跟 maintain effort.

若寫出個 Window 版 BIOS SETUP Menu, 保證你在台灣 BIOS RD 圈中, 會出名.

以前寫完 WinFlash, 就是想再做 Window 版 BIOS SETUP Menu, 但那時不知是
AWARD 沒訂 CMOS NVRAM List Spec, 還是 ASUS BIOS RD 故意不讓我知道.
現在是忙著搞更重要的事情, 沒有動力去寫跟 BIOS 相關的程式.

BIOS TEAM 對我相當有敵意, 因其組織重要性已不復當年.
這時若再推出 Window 版 BIOS SETUP Menu, 無異是挑戰 BIOS Team 的創新能力.
希望你能做出來, 從市場端給 ASUS BIOS team 一個刺激警惕.

KKMAN 提到...

Hi 小華你好
想請問一下讀寫nvram的方式,我知道讀寫CMOS可透過Port 70/71, 72/73但這樣也只能讀到128x2的資料,之前用過某家廠商的工具(透過該廠獨有的chip),它的nvram有8k左右,請問通常有什麼方法可讀取nvram,我聽人說是透過南橋,但我找了ICH9的data sheet,卻找不到方法,請不吝賜教,給我一些入門的方法。謝謝。

小賴 提到...

目前已成功寫出Windows下的Setup Utility了,相關細節就不太方便透露,基本上觀念正確~很多事情應該都做得到的~~

By the way~我是在EFI BIOS下, Windows x86/x64 based.