標籤

2009年3月13日 星期五

符合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處,得出數據表長度和數據表地址,即可通過地址訪問結構表。從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)為例説明格式區域和字符串區域的關係

位置

名稱

長度

描述

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

2009年2月25日 星期三

UFI

http://bbs.wuyou.net/viewthread.php?tid=127538&page=1#pid1430790

細節部分請上網下載Universal Serial Bus Mass Storage Class UFI Command Specification(PDF)。

BIOS透過USB總線(2.0的是通過EHCI USB)向USB存儲設備發送UFI指令來和它進行交流。
其中MODE SENSE Command(5AH)就是你所說的媒體介質、模式檢測功能,在返回的數據中包含了一個Media Type and Write Protect,裡面有介質描述符的字節(該字節在格式化的UFI命令中可以指定),BIOS就是根據這個來確認U盤的類型和是否有寫保護等。

系統對USB存儲設備訪問是採用用一種叫LBA的地址(目前採用的是LBA28),並沒有所謂的CHS,windows、linux等訪問USB儲存設備的時候並不使用BIOS的INT 13H,而是通過USB總線直接發UFI命令,採用的地址也是LBA,所以就不太存在兼容性問題。

然而U盤啟動引導程序卻是依靠BIOS的INT 13H來訪問。
BIOS的INT 13H對U盤的支援(不一定支援),就是把INT 13H中的C、H、S參數轉化成LBA地址,然而不同的BIOS設定的每道扇區數、每頭柱面數並不一定相同。假設我們有個U盤被自己機器的BIOS被認成16H、512C、64S,分區格式化后,分區的開始位置為0H、1CH、1S,分區引導程序所在的LBA是0000064H,另一台机子的BIOS認成16H、1024C、32S,那麼我們剛才做的那個啟動盤,分區起始扇區的LBA就變成0000032H,很顯然位置錯了,當然啟動不起來了。

BIOS對每道扇區數、每頭柱面數的不同設置就是導致U盤啟動不通用的根本原因。
也許你會說那麼我們引導程序干脆直接使用擴展INT 13H發送LBA包,GRUB就是這種思路,可是有的BIOS並不支持U盤的擴展INT 13H功能,並且在檢測的時候還會返回支持的假象-_-!!
其實386時代的硬盤也遇到這個問題,然而當時CMOS里面提供了硬盤類型參數的手動設置,再加上硬盤不是移動存儲設備,所以問題就沒那麼明顯了。

至於HDD、FDD、ZIP只是媒體介質描述的不同,並不能徹底解決CHS問題。

2009年2月16日 星期一

每個人心中 都有自己的priority

大家心中的priority是什麼?是親人?是朋友?是愛情?是工作?
我珍惜身邊的人,勝過一切,尤其是跟生命有關。

她時常抱怨我,為了工作忽略了她,我總是安慰。
但這次,我選擇明天的飛機回去,我並不是個喜歡與眾不同的人,很不喜歡這樣麻煩別人。
事情已經告一段落,剩下的時間留下又何妨,即使如此,我還是提出了需求。

我不喜歡故作悲傷,但強顏歡笑實在很累。

很多事有人不在乎,可我就是很care。
因為很多人沒有流過那眼淚,沒有感受那體溫。
當我鼻酸的那一瞬間,我知道,
曾經發生的事,是不會忘記的,只是想不起來而已。

我一直直覺事情不妙,但真的沒想到會來的那麼突然,所以接連好幾天妳的眼淚,我都只是安慰妳,
只是說服自己,眼淚不會流很久的,專心工作,人的生命是很堅強的。
我甚至出差前,才幫妳們搬家,才跟他一起扛書櫃,他才誇我懂事有禮貌。

如今,我卻再也聽不到老是抱怨爸爸管太多的女朋友了。

我曾經錯過太多,不是指情人節,不是指那段荒唐歲月,
或許是為了過去,或多或少的補償吧,或許是,無法再錯過了?

謝謝幫助我的人,也很感謝我遇到好的主管。
我知道我不是最需要安慰的人,我也知道有人覺得,女朋友的爸爸不是個好藉口,
我尊敬所有人心中的priority,也由衷的,謝謝你們的體諒。

2009年2月13日 星期五

PROCHOT#

http://it.sohu.com/20050228/n224465028.shtml


為彌補了第一代溫度監控技朮的缺陷,提高監控能力,Intel開發了第2代溫度監控技朮。

第二代溫度監控系統的一個突出特點是在微處理器內部集成了溫度控制電路(Thermal Control Circuit,TCC),由微處理器自身執行溫度控制功能,同時,微處理器內設置了兩個相互獨立的熱敏二极管,D1是本地熱敏二极管,所測信號提供給TCC,D2則為遠端熱敏二极管,其測量結果用于實現主板控制功能及顯示核心溫度,如圖8。




圖8 注∶第2代溫度監控系統框圖

我們先看看TCC是如何發揮作用的。TCC定義了兩種工作狀態:激活態和非激活態。TCC的狀態與PROCHOT#信號的電平高低相對應,PROCHOT#為低電平時,TCC為激活態,否則處于非激活態。當微處理器核心溫度達到警戒溫度(Warning Temperature)時,溫度檢測電路將PROCHOT#信號置為低電平,從而激活TCC。TCC激活后,采取“抑制任務周期”(Throttle duty Cycle)的方式(如圖9),使微處理器有效頻率下降,從而達到降低功耗的目的。當微處理器的溫度降低后(低于警戒溫度1℃以上),TCC回到非激活態,微處理器恢復到“標稱頻率”。可見,TCC實質上是一個由微處理器溫度控制的頻率調節器。



圖9 注∶TCC激活時,任務周期減少

如果發生災難性冷卻失敗的情況,使微處理器溫度超出极限溫度(thermal Trip),TCC將設THERMTRIP#信號為低電平,BIOS芯片檢測到這一變化后,直接關閉微處理器時鐘信號,並通過PWM控制器封鎖VRM向微處理器供電,直到溫度降到极限溫度以下,RESET#信號有效,THERMTRIP#才會重新變為高電平,系統才能繼續工作。否則THERMTRIP#總為低電平,系統就停留在暫停狀態。“當微處理器離開風扇的時候”,Pentium 4微處理器之所以能夠安然無恙,答案就在這里。

小知識∶警戒溫度與极限溫度有什麼不同?
微處理器警戒溫度(warning temperature)和极限溫度(thermal trip)都是指核心溫度,但它們所代表的意義有所不同。警戒溫度是能夠保証微處理器穩定運行的溫度;极限溫度也叫最高核心溫度(Maximum die temperature)或關机溫度(Shutdown temperature),是防止微處理器免于燒毀的溫度。

各款微處理器的警戒溫度和极限溫度值是制造商根据微處理器的制造工藝和封裝形式及封裝材料确定的,並在技朮白皮書中給出。為防止用戶自行設定而帶來危險,Intel已將Pentium 4微處理器的警戒溫度和极限溫度寫入TCC內的ROM單元中,用戶無法修改它們。

現在有不少主板的BIOS中也可以設置警戒溫度和關机溫度,不過可選的數值都比較保守,例如警戒溫度最大值為70℃、關机溫度為85℃,這是遠低于TCC內設定值的。

兼顧性能和可靠性是第2代溫度監控技朮的優秀之處。由公式P = CV2f(其中C是等效電容容量;V是工作電壓)可知,頻率f與能耗P之間是一種線性關系,降低頻率是減少發熱量的有效途徑。這種通過降低有效頻率實現降溫的措施,比之以前那種關斷時鐘信號的做法顯然要聰明一些,避免了因強行關閉微處理器,而導致數据丟失的情況。

Pentium 4處理器中的PROCHOT#引腳還有另外兩個實用的功能。其中的一個功能是向主板發出報警信號??PROCHOT#引腳為低電平時,說明微處理器核心溫度超過了警戒溫度,此時微處理器工作在較低的頻率上。如果超出警戒溫度(電腦用戶利用工具軟件可以獲得這個信息),應及時檢查散熱器安裝是否妥當,風扇轉速是否正常。

PROCHOT#引腳的另一個功能是可以保護主板上的其他元件。PROCHOT#引腳采用雙工設計??信號既可以從這根信號線出去,也能進得來。主板設計者可利用這一特性為供電模塊提供保護,當供電模塊的溫度超出警戒溫度時,監控電路輸出一個低電平到PROCHOT#引腳以激活TCC,通過降低微處理器功耗來達到保護供電模塊的目的。

可見,Pentium 4處理器不僅能自保平安,還能對供電電路提供保護,細微之處體現出設計者的良苦用心。同時,將TCC集成到微處理器內不僅對自身更加安全,也簡化了主板設計,降低了主板制造成本。可以說,第2代溫度監控技朮是一個給微處理器制造商與下游主板廠商帶來雙贏的技朮。

小知識∶如何設置BIOS中的“Processor speed throttling”?
Pentium 4主板的BIOS中通常有“Processor speed throttling ”之類的選擇項,用于選擇超警戒溫度后處理器任務周期(duty cycle)占全部周期的比例,在處理器頻率不變的情況下,這個比例越大說明處理器的工作效率越高。其中有“Automatic”和“On demand” 兩種選擇,“Automatic(自動)”表示任務周期的占空比為50%,也就是說比正常頻率低一半;“On demand(按要求)”下面有12.5%、25%、…、87.5%等多種選擇,選擇的數值越小,則任務周期的比例越小,降頻幅度也越大。

2009年2月12日 星期四

WIN98SE硬碟主引導記錄代碼反組合分析

[1]
   硬碟引導記錄MBR(Master Boot Record)是指硬碟之0面0道1磁區之內容,PC及其兼容機之ROM BIOS約定在上電及POST自檢成功後,將其從硬碟讀出,放置在記憶體0:7C00處,然後轉去該位址執行。該段代碼負責從代碼尾部之4個分區表項中找出可以引導的項,讀出其引導記錄引導之。

MBR在相當長時間內都保持著1982年IBM設計IBM PC機時的代碼原樣,直到硬碟容量突破傳統BIOS所能支援的最大容量8.4G之時,它才不得不加入新的INT13功能擴展代碼,不過主要的功能還是沒有改變。

; 硬碟主引導記錄代碼分析:
; 本段代碼取自由WIN98SE之"FDISK /MBR"命令處理過的硬碟
;
; PC機之ROM在上電及POST自檢成功後,將本段代碼從硬碟之0面0道1磁區位置讀出,
; 放置在0:7C00處,寄存器設置如下:
; CS=DS=ES=SS=0. IP=7C00h, SP=0400H
;
; 本段代碼負責從代碼尾部之4個分區表項中找出可以引導的項,讀出其引導記錄引導之。
;
; 流程如下:
;
; 1). 將代碼從0:7C00移至0:600
; 2). 檢查4個分區表項有效性:
; a).有否可引導分區?
; 無則轉ROM BASIC(INT 18)
; b).多個引導分區?
; 是則顯示'Invalid partition'後掛機
; c).可引導標誌為0與80h之外的無效值?
; 是則顯示'Invalid partition'後掛機
; 3). 找尋唯一有效引導分區專案,將之對應的引導記錄讀入0:7C00,
; a).讀入方式有二種,
; 一般採用經典的INT13 AH=2號調用,
; 如果是0Eh系統ID,則使用另一種新型BIOS之INT13 AH=42號擴展功能
; b).如果讀入操作錯誤(包括讀入內容無效)就重複讀10次, 如果系統ID為0B,0C,因為它們在原引導記錄之後6個磁區位置 還有一個引導記錄的備份,就從第6次開始讀該備份
; c).仍然錯誤則轉顯示'Missing operating system'或 'Error loading operating system'後掛機
; 4). 轉向有效的引導記錄0:7C00
;
; 它載入引導記錄至0:7C00,轉向它時,寄存器設置如下: CS=DS=ES=SS=0. IP=7C00h, DI=SP=7C00H, SI=BP-->指向引導中的分區表項
; .386p
_data segment public
assume cs:_data, ds:_data
org 600h
mbr proc far
; The ROM in the IBM PC starts the boot process by performing a hardware initialization and a verification of all external devices. If all goes well, it will then load from the boot drive the sector from track 0, head 0, sector 1. This sector is placed at physical address 07C00h. The initial registers are set up as follows: CS=DS=ES=SS=0. IP=7C00h, SP=0400H, CLI.
組合代碼:
0000:0600 start: ; relocate to 0:0600
0000:0600 33 C0 xor ax,ax
0000:0602 8E D0 mov ss,ax
0000:0604 BC 7C00 mov sp,7C00h ; new stack at 0:7c00
0000:0607 FB sti ; interrupts ok now
0000:0608 50 push ax
0000:0609 07 pop es
0000:060A 50 push ax
0000:060B 1F pop ds ; ES:DS=0
0000:060C FC cld ; movsb direction: forward
0000:060D .BE 7C1B mov si,offset loc_restart - 600h + 7C00h
0000:0610 .BF 061B mov di,offset loc_restart
0000:0613 50 push ax
0000:0614 57 push di
0000:0615 B9 01E5 mov cx,offset code_end - offset loc_restart
0000:0618 F3/ A4 rep movsb ; move CX byte data from DS:SI to ES:DI
0000:061A CB retf ; return address = 0:061b = offset
loc_loc_restart

; look throught partition table
; for valid & activate entry
0000:061B loc_restart:
0000:061B .BE 07BE mov si,offset partition_tab
0000:061E B1 04 mov cl,4 ; number of table entrie

0000:0620 loc_nextpe:
0000:0620 38 2C cmp [si],ch ; is boot indicator <= 0(ch=0)?
0000:0622 7C 09 jl short loc_boot ; < 0, that is 80h, bootable entry found
0000:0624 75 15 jnz short loc_bad ; !=0 & !<0, that is invalid (0 & 80h only)
0000:0626 83 C6 10 add si,10h ; = 0, go partition next entry
0000:0629 E2 F5 loop loc_nextpe
; no more entries to lookup
0000:062B CD 18 int 18h ; no bootable entries - go to rom basic

0000:062D loc_boot: ; xref 0622
0000:062D 8B 14 mov dx,[si] ; head and drive to boot from
0000:062F 8B EE mov bp,si ; save table entry address to pass to partition boot record

0000:0631 loc_nextrpe: ; all remaining entries should begin with 0
0000:0631 83 C6 10 add si,10h ; next table entry
0000:0634 49 dec cx ; # entries left
0000:0635 74 16 jz short loc_tabok ; all entries look ok
0000:0637 38 2C cmp [si],ch ; other entries = 0 ?
0000:0639 74 F6 je loc_nextrpe ; yes, this one is ok

0000:063B loc_bad: ; found a invalid entry :
; A). from 0624: boot id !=0 and !=80h
; B). from 0639: multi entries with id=80h
0000:063B .BE 0710 mov si,offset msg1+1 ; 'Invalid partition'

0000:063E loc_halt: ; show msg then halt
0000:063E 4E dec si
0000:063F loc_msg: ; xref 064B, 06BA
0000:063F AC lodsb ; got a message char
0000:0640 3C 00 cmp al,0
0000:0642 74 FA je loc_halt ; no more char, then halt
0000:0644 BB 0007 mov bx,7


[2]
0000:06C1 loc_int13ext: ; xref 0686, 06A1
0000:06C1 98 cbw ; al=01 so ax=0001
0000:06C2 91 xchg cx,ax ; cx=0001
0000:06C3 52 push dx
0000:06C4 99 cwd ; dx:ax = start_sector
0000:06C5 03 46 08 add ax,[bp+8] ; rel_sec (lo word)
0000:06C8 13 56 0A adc dx,[bp+0Ah] ; rel_sec (hi word)
; dx:ax = logic sector #, cx=# of sec to read
0000:06CB E8 0012 call int13ext ; call int13ext to read in boot record
0000:06CE 5A pop dx
0000:06CF EB D5 jmp short loc_int13extback
0000:06D1 loc_retry: ; xref 06A6
0000:06D1 4F dec di ; dec retry count
0000:06D2 74 E4 jz loc_endofretry
0000:06D4 33 C0 xor ax,ax
0000:06D6 CD 13 int 13h ; Disk dl=drive ? ah=func 00h
; reset disk, al=return status
0000:06D8 EB B8 jmp short loc_readin
0000:06DA 00 00 00 00 00 00 db 0, 0, 0, 0, 0, 0 ; reserved

mbr endp

; INT 13 extended read --------------------------------------------------------------------------------
; Entry:AH - 42h
; DL - Drive number
; DS:SI - Disk address packet
; Exit: carry clear
; AH - 0
; carry set
; AH - error code
; This function transfer sectors from the device to memory. In the event of an error,
; the block count field of the disk address packet contains the number of good blocks
; read before the error occurred.
;
; DS:SI -> Device address packet
; Offset Type Description
; 0 Byte Packet size in bytes. Shall be 10h.
; 1 Byte Reserved, must be 0
; 2 Byte Number of blocks to transfer. This field has a maximum value of 127 (7Fh).
; 3 Byte Reserved, must be 0
; 4 2Word Address of transfer buffer. The is the buffer which Read/Write operations will use
; to transfer the data. This is a 32-bit address of the form Seg:Offset.
; 8 4word Starting logical block address, on the target device, of the data to be transferred.
; This is a 64 bit unsigned linear address. If the device supports LBA addressing this
; value should be passed unmodified. If the device does not support LBA addressing
; the following formula holds true when the address is converted to a CHS value:
; LBA = (C1 * H0 + H1) * S0 + S1 - 1
; where: C1 = Selected Cylinder Number
; H0 = Number of Heads (Maximum Head Number + 1)
; H1 = Selected Head Number
; S0 = Maximum Sector Number
; S1 = Selected Sector Number
0000:06E0 int13ext proc near
; input dx:ax - 32 bit of logic sector address to read in
; cl - number of sector to read
; es:bx - buffer to hold data
; output carry clear if sucessful
; es:bx - end of read-in-data + 1
; carry set if error
0000:06E0 56 push si ; 10
0000:06E1 33 F6 xor si,si
0000:06E3 56 push si ; E
0000:06E4 56 push si ; C
0000:06E5 52 push dx ; A
0000:06E6 50 push ax ; 8 - 4W: Starting logical block address (dx:ax)
0000:06E7 06 push es ; 6 - 2W: Address of transfer buffer (es:bx)
0000:06E8 53 push bx ; 4
0000:06E9 51 push cx ; 2 - BY: Number of blocks to transfer
0000:06EA BE 0010 mov si,10h
0000:06ED 56 push si ; 0 - BY: packet size = 10h bytes
0000:06EE 8B F4 mov si,sp
0000:06F0 50 push ax
0000:06F1 52 push dx
0000:06F2 B8 4200 mov ax,4200h
0000:06F5 8A 56 24 mov dl,[bp+24h] ; boot record drive
0000:06F8 CD 13 int 13h
0000:06FA 5A pop dx
0000:06FB 58 pop ax
0000:06FC 8D 64 10 lea sp,[si+10h]
0000:06FF 72 0A jc short loc_ret

0000:0701 locloop_0701: ; move dx:ax to point end of buffer
0000:0701 40 inc ax
0000:0702 75 01 jnz short loc_0705
0000:0704 42 inc dx
0000:0705 loc_0705: ; xref 0702
0000:0705 80 C7 02 add bh,2
0000:0708 E2 F7 loop locloop_0701

0000:070A F8 clc
0000:070B loc_ret: ; xref 06FF
0000:070B 5E pop si
0000:070C C3 retn
int13ext endp

0000:070D loc_gobootrecok: ; xref 06B1
0000:070D EB 74 jmp short loc_bootrecok

0000:070F 49 6E 76 61 6C 69 msg1 db 'Invalid partition table', 0
0000:0715 64 20 70 61 72 74
0000:071B 69 74 69 6F 6E 20
0000:0721 74 61 62 6C 65 00
0000:0727 45 72 72 6F 72 20 msg2 db 'Error loading operating system', 0
0000:072D 6C 6F 61 64 69 6E
0000:0733 67 20 6F 70 65 72
0000:0739 61 74 69 6E 67 20
0000:073F 73 79 73 74 65 6D
0000:0745 00
0000:0746 4D 69 73 73 69 6E msg3 db 'Missing operating system'
0000:074C 67 20 6F 70 65 72
0000:0752 61 74 69 6E 67 20
0000:0758 73 79 73 74 65 6D
0000:075E 0025[00] db 37 dup (0) ; reserved space for message translation

0000:0783 loc_bootrecok: ; boot record ok, xref 070D
0000:0783 8B FC mov di,sp ; sp=7C00
0000:0785 1E push ds
0000:0786 57 push di
0000:0787 8B F5 mov si,bp ; ds:si -> 7C00
0000:0789 CB retf ; jump to 0:7C00 (that is boot record)

org 07BEh

part_table struc ;Offset Size Description
boot_ind db ? ; 00h BYTE boot indicator (80h = active partition) 0 - boot indicator
start_head db ? ; 01h BYTE partition start head
start_sector db ? ; 02h BYTE partition start sector (bits 0-5)
start_cyl db ? ; 03h BYTE partition start track (bits 8,9 in bits 6,7 of sector)
sys_id db ? ; 04h BYTE operating system indicator (see below)
end_head db ? ; 05h BYTE partition end head
end_sector db ? ; 06h BYTE partition end sector (bits 0-5)
end_cyl db ? ; 07h BYTE partition end track (bits 8,9 in bits 6,7 of sector)
rel_sec dd ? ; 08h DWORD sectors preceding partition
num_sec dd ? ; 0Ch DWORD length of partition in sectors
part_table ends ;Values for operating system indicator:
; 00h empty
; 01h DOS 12-bit FAT
; 04h DOS 16-bit FAT
; 05h DOS 3.3+ extended partition
; 06h DOS Large File System
; 0Bh DOS 32-bit FAT
; 0Ch DOS 32-bit FAT
; 0Eh DOS 32-bit FAT
0000:07BE 80 partition_tab label byte ; xref 061B
1boot_ind db 80h ; bootable
0000:07BF 01 01 00 0B 7F 7F 1start_head db 01h
1start_sector db 01h
1start_cyl db 00h
1sys_id db 0Bh ; DOS FAT32
1end_head db 7Fh
1end_sector db 7Fh
0000:07C5 C8 3F 00 00 00 41 1end_cyl db 0C8h
1rel_sec dd 0000003Fh
1num_sec dd 00383B41h
0000:07CB 3B 38 00 00
0000:07CE 00 00 41 2boot_ind db 00h
2start_head db 00h
2start_sector db 41h
0000:07D1 C9 05 7F FF 13 80 2start_cyl db 0C9h
2sys_id db 05h ; DOS extender
2end_head db 7Fh
2end_sector db 0FFh
2end_cyl db 13h
0000:07D5 2rel_sec dd 00383B80h
0000:07D7 3B 38 00 80 BA 28 2num_sec dd 0028BA80h

...
org 07FEh
0000:07FE 55 AA magicword dw 0AA55h

code_end label byte ; use this labelt to get length of code

_data ends ; xref 0615

end start


http://www.hkitn.com/article.php/1219
http://netwinder.osuosl.org/users/n/nelson/public_html/internals/mmap-7c00.html
http://www.programmer-club.com/pc2020v5/forum/showSameTitleN.asp?board_pc2020=assembly&id=7016&keyword=