找回密码
 加入计匠网
搜索
热搜: BIOS ACPI CPU Windows
查看: 60183|回复: 39

戏说BIOS

[复制链接]
发表于 2009-7-6 16:05:24 | 显示全部楼层 |阅读模式
戏说BIOSHello BIOS; f% r) I7 ]4 |$ f/ y

4 Z: x, H* j/ q& x* F3 ~' v$ z4 D
我所知道的EC”系列基本结束了,现在我终于可以有空玩一玩BIOS了。可是需要特别强调的是我是一名EC而不是BIOS,所以我看BIOS的视角可能会不够专业,也不够正统,这也是为什么我将这个系列取名为戏说BIOS”的原因。可能有些朋友会觉得我不务正业,身为EC却去玩什么BIOS(呵呵我本来就是不务正业J),我觉得PC本身是一个非常复杂的系统,从经验来看很多问题都不是孤立的,通常会牵扯到很多的环节,因此如果将视野局限于自己的一亩三分地则很有可能见树不见林,看不清问题的本质。所以我觉得全面细致的理解系统的各个环节非常有必要;而且我的技术目标也是希望通过n年的努力能够贯通PC系统从EC->BIOS->OS->DRIVER->APP的整个链条,把握系统的运作的脉络。关于这个“戏说BIOS”系列,我打算先练习一些BIOS新人学习作业,如:cmos dumpkbc accesspci scansmbiosdump等等;然后在对我感兴趣的一些BIOS的领域做一些study。现在让我向BIOS世界打个招呼吧: “Hello BIOS,I am coming!”
6 P4 m" H" k7 x& ?3 j7 v% l: s4 v- C
data segment
4 y& b& G$ F6 H, v& n7 B1 n. d
6 n4 R4 n8 a7 ?4 t9 S/ N9 v1 iHelloBIOS db 'Hello BIOS,I am coming!$'
" l8 m: L/ I$ o* `! I* U- u# n

2 J+ Z6 K" @/ h: {data ends! n% L" q$ X% i4 J4 e

4 c' u. P2 T" Y3 C. g+ m* l5 H6 J% ecode segment) t2 ~$ Y6 x, I, T5 f* H8 M6 _; r, Z% k
) W8 l: u4 H: Y# A1 n9 o3 t
assume cs:code,ds:data
& u$ l& F7 e5 i* c- n! F7 ^

$ d; c1 c% J2 ~4 E0 tstart:+ B; ?- f' _  J: C; G3 I5 y# u

/ V; Y" W4 b/ _3 Kmov ax,data
- Q9 \+ |6 C8 l# s! y$ s  ?5 g

* P; Q2 \& I- C& {3 k% n" c6 Hmov ds,ax
' v4 U2 C" [, D$ ]

- q' A! Q0 {) l) e2 C8 t$ p7 Qmov dx,offset HelloBIOS

  G8 ~: t8 a" Q! s' h1 H; `/ U1 {! W2 \6 ?9 X6 k% A6 ]6 \/ U2 u
mov ah,9

2 [# x" u: B3 Y0 s# ?4 z
: b: O4 h9 f% ^7 ]  _4 @int 21h
3 T5 e. J. x1 M1 m7 k' Z
/ o  g+ Y. S, W& k  ?2 u3 @
mov ax,4c00h
  B" `' x: p+ C# g2 M. K2 ]& s+ B. e' D- N& j+ ]( S8 B2 G. g
int 21h
' P2 r- P8 N! w, f5 ?2 ~# J

& ~! R" E4 f% {& Kcode ends
  v2 o% g" Q2 k- ]/ S* H  T
$ E0 Y' K- d1 P5 _/ m7 vend start$ u3 ?. U: m5 A9 r3 `# v! U. X! f+ n5 G1 L
! J4 p( |5 @0 L0 Q
That’s all!
: U) z/ I. m' A$ r& j% K% }$ @& mPeter
8 r3 G; U! F% w8 j
* t+ R' f: ^+ p# M/ ~, Q[ 本帖最后由 peterhu 于 2009-7-8 09:13 编辑 ]
 楼主| 发表于 2009-7-6 16:07:54 | 显示全部楼层
戏说BIOSCMOS
$ _7 W; ]2 h1 l- N& H

- O2 x2 u, |1 }/ n) y/ u1. Introduction
$ E0 f6 e7 v2 f! _7 s6 \/ B  s- j3 I( e- c2 p6 [
CMOS全称为complementary metal oxide semiconductor, 翻译成中文就是互补金属氧化物半导体,它是由一颗小的纽扣电池供电的128/256 bytesram(现在的chipset通常提供256 bytes或者更大的空间)。它主要用于存放RTC以及一些oem的系统配置信息,所以除了RTC等部分其它的很多信息都是undocumented& non-standardRTC 标准的(documented&standard) ram bank如下表 1 所示:* r: \- I8 `" R: k+ M. B
# a, {6 A0 x) ?" D: a6 B: `' H) y
Index
) y( }! \+ v, E0 s8 s
Name
/ i2 a2 R  o0 z4 O5 z0 |
00h/ \6 a1 ^5 g; X6 w; C
Seconds. R5 B/ ~4 @8 T: \2 Q
01h
; ^$ R/ _5 V0 K! Z
Seconds Alarm
: @' r0 M4 E; @1 g$ s, m
02h, [* P4 }4 C9 P5 t# _2 B
Minutes
% \3 t5 z* @2 @! y
03h* g4 v  K$ ?  Z+ j/ v" @% T, w6 l
Minutes Alarm8 H- y1 |2 q7 H2 y5 g
04h
1 \6 ?6 G5 G* a7 W
Hours. V6 W5 Q0 p6 k4 K
05h, ~6 q" i6 [% ?+ a5 M) J1 I1 u
Hours Alarm
3 ^+ _* d3 U) k
06h. [- z+ t1 S2 p6 n. x
Day of Week" U, U# B5 u$ S; l
07h
) D; D8 J# Y% L  |+ j! A0 d/ }7 A
Day of Month( v& O/ @8 n9 i- C% V0 Z
08h
% v: G" X2 T0 F
Month, x% t9 e4 i+ e6 ?# G5 p
09h% e) z5 G) {8 n5 m. N
Year
, o0 |) Q$ P* G9 b# o
0Ah! i* C- }( P* u
Register A. [. w4 t+ G# a, C6 s$ f
0Bh
3 X9 g% q9 q# S7 C
Register B* `* g* z3 R% }; A/ F8 a
0Ch( k8 ]7 ~6 r; f$ \9 B3 m
Register C6 |" `  O' t+ d3 B
0Dh7 {( l6 {2 R6 D, e0 f$ j
Register D
5 d/ T& n6 p% C) ~
0Eh-7Fh
( X; |2 L4 x' S8 `
114 Bytes of User RAM
# H, X$ ^" m4 B, a- `+ B; Z5 W: l
                 表 1
( b  T2 E; d: M
# G+ d- l- l; s- J0 c* y" J2 p2. Access Cmos
; f7 Z6 P1 r' J4 K: Z
/ @5 p+ i! b" G: r# z' A% J+ Y7 b5 Q8 p9 B, u2 e7 V+ m4 l
访问cmos通常是透过70h,71h这两个IO port实现的,有些chipset支援256 bytescmos ram,访问128bytes以后的空间需要开启chipset的始能register,有些chipset使用72h73h访问扩展的空间如intel chipset,有些仍然使用70h71hsis chipset,因为这部分是非标准的,故后面的练习程序就不去读写这部分ram space。读写cmos的过程非常简单,读特定的index的内容只需要将index送给70h,然后就可以从71h读出对应的数据,具体过程如下述code所示:
9 p0 M& C& E" K7 S! ?1 p5 ?
;----------------------------------------------------------------------------# `: Z7 W3 k9 j& S7 {  J2 Q

* b. g" n9 Q: X# j& N  t2 y( x/ V% X) Y' a;read_cmos
2 v3 Q$ T& m# V;read the contents of a specific CMOS register
' ~. e) m( E1 W: ^. g;call with
+ Z! |) K  _+ v:al = CMOS address to read5 o, v! S1 R+ W9 Q* W5 k
;returns
6 e' u$ j4 l- ^, k) [7 O# C:ah = Contents of register
1 a2 l! e& n3 J6 U, C;used registers: ax9 X0 H& M6 E) v6 B! c
;-----------------------------------------------------------------------------% ?( [4 P" F! R  k. ]; r
read_cmos proc near* i$ W# I3 h  }8 _2 J0 |

! S  R: m$ N8 ~# ^, S( f& h  v3 K+ [# y, h! f) _/ L; ?
cli
" O% p3 \9 i& C# F' T
6 k  @  }* w, b# f' j/ p
or al,80h;disable NMI
9 I! Z* [6 W9 Q+ B

& y! p4 P& B3 Aout 70h, al

6 D- S9 h5 f+ S. p7 z$ z8 O* \" P  u3 a0 w+ l7 G0 v' B
call io_delay
" Q6 g4 o- M* {/ Q# Q2 ^9 \

$ g6 e$ d1 w0 L8 n, T8 Z. Bin al, 71h
2 F5 A) v! a$ d: l7 F

7 n2 A: X4 N& gcall io_delay

( v" N  g2 q, w) g
, v! s& L* i. w9 kmov ah, al
/ o8 N; V  k% Z+ g7 l5 y
& w+ y3 F: m. ]
xor al,al

/ y; x  Q, V3 X2 N
4 ^, O% \. }! A- j* J4 H7 l+ Dout 70h,al ;enableNMI
$ W7 e! n  H& e

7 Q8 ~) r6 `/ g% R. V6 Zsti
  f7 Z, W' s' i, y
6 N6 ]4 }$ x- g- e
ret

' o& O' J! K$ @' S4 g$ [( i+ i+ _9 z9 ^- V. C1 K! r
read_cmos endp
! M0 s0 W8 y* {( l' N2 i3 a写操作和读类似,只是要将待写入的数据送给71h即可代码如下所示:9 P6 ~+ p9 o5 R6 n) h2 z! A
;----------------------------------------------------------------------------8 w% R$ q; A( O4 e& V

/ ?" y: v% P1 W/ k;write_cmos
: w- ~+ j% M" k4 N0 m- W* L;write the contents of a specific CMOS register
$ b1 j+ A3 A/ P% g1 L' i;call with( b- I, \9 V4 E! s# D, g  _
:al = CMOS address to write0 I9 g5 a7 t2 h) N
;ah = Contents of register
' ]! q1 v; B# [;returns:NULL
8 Z+ g9 Z- _  L) z9 ?/ A;used registers: ax- I. V- C9 j4 n# D' j5 I
;-----------------------------------------------------------------------------
( w8 N1 c* B7 a( G# W/ p! \write_cmos proc near
! o% p1 @1 u  @! Q9 F( ~* @: D3 O* I9 T# }: e# |
cli
/ Q- Q6 `2 A, v; |# U) o

: R. R; ~/ j% m( h  e% Z! `$ Ror al,80h;disable NMI
; o* {% |1 X) K" j% l8 O

4 o( r, y8 L+ l8 W+ y, j) rout 70h,al

. E0 K! ^' r, z
0 F+ R; m+ ^. e- Q( Ucall io_delay
- ^: H* x4 A6 z+ |3 K; B# }% T4 e
1 j: Y5 X0 l/ }/ c% n
mov al,ah
! j( S+ n& A" A! E4 {5 s
, g6 @# T& x( j7 \
out 71h,al
6 R. S/ l. H" o4 Y) t' n2 T! M
6 A5 y) }4 V  M; k
call io_delay

* u7 B( T+ C/ S8 O  u7 n! x2 {* k, \7 [6 v4 C" H5 ~* J, ?7 x0 o( p
xor al,al
' T/ a1 P, q7 q+ E/ P; L5 ^7 E- J
4 }( H$ F! p# n5 @+ V: R7 }
out 70h,al ;enableNMI

6 N. W- A5 s# b& H7 g9 b5 p7 c( d( U! {6 [& u- ?! Q
sti

0 }4 \6 M  T/ h) z' \+ L- T7 b
6 _3 {$ ]6 Y: g6 D  _+ }ret
$ c! }2 j; l0 |9 s
7 `# s- c3 f. D3 V2 X. a$ e5 f1 Q
write_cmos endp( n2 _: G( s9 Y3 |' L
- h4 p4 j- C& R" }! o
另外有些细节需要注意的是:a.读写过程中都需要关掉中断以防止,中断处理程序访问CMOS以及RTC更新过程中可能会导致并发访问。b.NMI(non-maskable interrupt)是一种中断向量为2的中断,但是与常规中断不同的是它不能通过mask register屏蔽掉而且sticli指令也对它无效;NMI通常用于一些无法恢复的硬件错误,访问CMOS时也可能产生NMI,所以需要关掉。NMI可以通过70h bit7做开关。c.状态寄存器A bit7记录了RTC是否正在更新,如果正在更新则等到更新结束再去读RTC(我写的cmosdump因为偷懒没有检查这一个bitJ)。/ l9 W3 m" m8 E4 D; ?% T' |

+ Y$ ]8 Q; M8 }) g3. Msg Based Event Driven8 C2 w" P5 O1 K. N) F

- D2 F! X$ O7 k9 A* P, Z1 n% U  M7 C# |# {9 @
知道了以上的知识,我就有能力写一个类似RUdump cmos的工具了下图1就是我写的cmosdump

+ ~5 {4 t/ Y6 ^) z) \% A
" b5 ^( s' ?' i. s$ ?8 p cmos1.GIF
  H# Q$ V5 {& t+ }  P) Q我觉得访问cmos本身并不困难,画个UI倒是挺费劲的,一个劲call vbios
7 X5 ^. Q3 v* \. A另外在完成这支tool的过程中我更深刻的体会到知识是相通的了,windows编程的经验在这里发挥了优势,为了能够动态更新,实时修改我就借鉴了windows下的“基于消息,事件驱动”的机制Mainloop->GetMsg->TranslateMsg->DispatchMsg一路下来好不快活!这部分的代码如下所示:7 i  x8 g8 T! B  z, f  Z0 S
- I: P" Z( K8 ^; Y1 O* B4 y

1 H3 n. T# x/ u, Z" Ymainloop:
  l4 V7 A9 y! n, y8 B6 j
/ a/ e+ F. Z3 W, J9 {! ]call show_index

; X" M, o$ }6 p$ `: I! t& k6 @% @* ^2 W6 r9 C5 `
call show_cmos2 C* C) u, g* \3 r
* {. J1 X$ D( T7 L- j
input_msg:
5 _! S' p. P3 x% B, h$ R7 K) t/ \3 w: Q& I1 g
mov ah,0

' m, W. {3 b+ _. D1 W( y: n' h
0 Q! Z- A! t4 ?int 16h

/ s2 T4 w/ Z4 B: Z" y5 \" Z& G! g. p) y
cmp ah,01h ;esc
9 s0 h7 h5 F3 I
1 i, ~4 H% b3 j
je exit

5 f3 X4 b6 X4 @( j( m0 {# ]6 \$ A1 b+ i& Y
cmp ah,48h;up arrow
4 A* w% s- L5 }5 G& @2 G

, @1 J7 q8 r+ X( @' h/ Yje up

3 V5 \+ e6 o4 E3 i- G
$ b$ v! e+ F2 x5 xcmp ah,50h ;down arrow

8 _' n" @) m( s3 a8 |# u* b
  k* w: P! A: |- r1 |* F; Pje down

. d5 S$ n6 L  Y4 o. l* F
0 g1 ^2 J* |2 o% o+ ], kcmp  ah,4bh;left arrow
3 y0 t) W$ ?7 q5 r

: V7 \3 }' b% _; ]3 \je left

  s- N( E8 Z" J
; Q0 V( ~$ F0 ~* l- B: W' R( Xcmp ah,4dh;right arrow

* d( B6 j* z, c6 a4 o% _8 l3 M+ ~! h$ E$ @7 u- d: a' F; k- ]
je right

6 l# [9 K3 U! X5 N
2 l4 _  C& x( ^, \
3 ~) O8 v7 i0 Z, p3 Qcall input_byte

1 E6 h6 w4 H! ]5 `3 Z
9 S5 S) b; Q! Ycmp bl,1

' S! l5 W3 h8 Q$ o1 H! o, v3 N
4 Z# a$ Q" D" X! p- l! Xjne msg_loop
. ~7 }0 Z0 _; Z1 v  Z# K& \
1 Z" q  e; q: O' u- \
mov ch,ah

" n$ r" \7 A0 o1 v7 ^* p
4 p* }0 |3 ^( Y2 ymov ah,0
: [" f9 X  y$ D
* G* M6 m4 Z- ^, m8 T
int 16h

  z/ H6 ^! l- W/ ~/ `8 U# ~6 U- e0 I6 S, |- ~" |, U3 P7 A1 J- x
cmp al,0dh;enter
  Y. Q$ }, `! F6 F) P" i
2 {8 W; M$ e; N1 S9 n1 w+ G# K/ ?
je enter

6 h" J5 V) k$ E- ]+ ~1 h
* v8 d) w8 M: R/ w: `* [& f5 `1 Rjmp msg_loop
6 a  g6 H; f8 @3 t- H3 M
) ^3 Z5 V9 C/ y2 O
enter:
  E/ s$ t, Y. ?9 d/ S
4 l) S$ g  |4 z, K
call get_index
$ s( ]( Y& s% E: ?. h& B0 k

: B- |7 Z- f/ [2 qmov ah,ch

: i# M0 m- w- r( B* E3 b" B8 O; ?; \/ V) {+ R" y/ e3 `& e
mov al,INDEX
% W1 p) l3 m0 v7 Z2 v

8 x  W: o4 E! @, ~call write_cmos

+ I7 v  h, I* U) U* ^9 o6 \" }. a. @& A& p3 a' G' ]) Z
5 v3 ?8 r7 @3 L# q0 \( z2 ^' c  S
msg_loop:* y$ y+ k: N# S2 ^4 z- Q

& ?5 D# x! E" }. s- Q  o4 L3 l# |8 H  a4 h
jmp mainloop

) i5 L$ i* C5 c( R
7 H- z1 N8 O/ O( G; Q& ]+ b

1 ]7 ~/ |. R: t% H4 Qup:
  [  V& C) C: S, ?  |: ^8 P5 p8 F* j3 X( d: `9 V: F  p! T
cmp ROW,MINROW
: s2 O) y$ a9 P2 z/ i
# C$ o! L( a+ C& N  l
jbe roll_up

- {& q" g5 T1 [: b# C2 o
% A5 p& r" g9 {$ U2 _! f6 ?% Jdec ROW
" p6 C, A2 F: `  U8 p
: d2 g, V* Q/ V. x2 l- {" U7 }
jmp bypass_up

0 Z- @4 d1 ]! U! V: y1 l/ Z6 k! x
& n; X/ s: C- C0 U, F4 w6 rroll_up:
+ y/ T  t; L9 F! g0 g6 v" ]

9 L: P4 P, V; ~' N$ mmov ROW,MAXROW

" u' ]9 E5 H1 J, a: d2 @- N' r# c
2 ^3 A) J2 z# a4 P# N% F" L" ^. Q6 }bypass_up:
( x5 ]' F  o6 a. D4 k# Y" C4 x) \& @2 e1 Q; D) C  Y
call set_cursor
9 T# Q% O, B; @% c* `

5 J7 F1 L' }- z, _: k! wjmp mainloop
. L! ]- c, M" h
$ I! N  k8 B" T( g
down:
) J( d& a- o. O

3 V  U& d. t4 _" U1 Q9 lcmp ROW,MAXROW

3 C6 D) C1 Z0 }: E  @4 `0 G3 h! m% `/ O9 u; x+ C; ?
jae roll_down

+ M* F; y# w, z2 ]) C, {# k5 S& B$ R. y% ^
inc ROW
/ o: X* g- Y# d# f2 Y

- @# U, i" R4 y& G) ejmp bypass_down
; O) c" W5 N( }8 P+ K3 k* R

' y% U( {' F6 {, {6 R' P: yroll_down:( V" m; B) t! |8 c
, \7 k% b! ^% m" }" S* Z( }
mov ROW,MINROW
9 s) G0 [( v' J. R5 I6 I
9 w* r. v0 Y1 Z" O2 y1 O, }
bypass_down:" m  h* C- y5 j
3 A/ A8 B/ T# f/ q/ }: W, \/ |1 Q
call  set_cursor
/ ^1 p6 V+ l7 G

- D% B1 N$ K" e# V" }jmp mainloop
" T6 `; l5 k8 V' W8 ^
: ~* L1 I# g" D3 w
left:
; R) Y; `" s, \) }$ {( Z. ]; J1 g5 }$ R
cmp COL,MINCOL
- V  c& p! O0 e$ k  _8 t! ]
" d1 C3 q3 g9 n2 D* N( Y5 u
jbe roll_left
% Y. a9 N, f* d
' N8 l: m5 F( t3 p
sub COL,3
$ G6 Q* T+ T) R: O) Z3 A  b4 z

& }4 A: S/ K; }& a* D8 w# xjmp bypass_left

3 r8 I7 g/ `) M7 y% C8 v! s
/ V: Q% V5 P0 ~: R1 o2 proll_left:
+ L; u  k, n/ E/ p  N6 t
, I7 q7 I' T! r  E2 a6 xmov COL,MAXCOL
/ k" e  x1 z& r2 l! z; X+ j6 w

- W" \1 c1 C8 E( x) w1 F  M! M1 Zbypass_left:
# T1 Z0 e! O. x) v. o8 K
* b. r/ O7 w8 M' w6 d8 x% [call set_cursor

  S' P: ?: n4 E, P! a% {# v. F. x5 N" u  X
jmp mainloop
$ C/ G7 `; G' B+ h/ ~3 [# A  [

( A( B% O, \7 J4 k+ C. Uright:; J: t& P2 E. k* Z) j
0 h( E: v. z, V  ~) j# K+ R) H( Y, E
cmp COL,MAXCOL
+ y2 H. R' A) S- }- g

2 m  K% W9 W9 ^4 Qjae roll_right
6 [2 F7 d" D$ t( {& t' m) v
2 h6 U# e6 N( U% D- V6 H: b
add COL,3
3 t& {9 T4 y  `* l+ h1 M% B, P
/ c3 @& ^( m' \$ I
jmp bypass_right

! Z: Q4 q* k4 L4 L, o% x
5 a/ I8 z# z. u: m  M4 l6 iroll_right:* h  ?0 i% E8 z) l3 ]* ]2 J6 ^

" I$ Z: J3 q9 T1 l/ \. HmovCOL,MINCOL
% n% P; \1 n! b) ^: e
9 Z5 y; s* R2 ^; k
bypass_right:
6 Z# k. [% H" E4 \; n8 f, q$ ^
' w+ o3 U/ V) w& a3 wcall set_cursor

( d% D3 B3 K, l; ]
# t, K  X: p5 _! v; I/ w# I$ V9 F& N5 Wjmp mainloop

! s& \" r+ L  F6 s( J
8 U0 D# O7 h4 V7 O* v" }7 ?

1 V- o1 m2 ?6 \6 x: aexit:- b$ {) L( Q8 o$ p) S: q4 v
$ }' v" g* s& n2 K, i5 c0 S
callclr_screen9 p5 F; P' N7 [3 B$ U" t

0 @4 W. ~. r; G7 S7 S4 `% A  Hmovax,4c00h! \. }' M+ ~9 Z! ~9 f9 X( T( X

! W" A- |* `4 `# X0 }. o: n. b8 Rint  21h1 j8 z9 }2 K$ T5 X1 c- G

5 G: s6 e: F: K1 }以上就是cmosdump.exe的核心架构J,完成以后觉得使用asm好别扭啊,可能是c/c++写的太多了,有点适应不过来了,以后还是要多写asm,增强驾驭asm的能力,让我的asmc/c++一样熟练。最后开放cmosdump.exe完整的source code供有兴趣的朋友参考,source code和可执行文件在附件下载
4 l2 s& D; o6 F) o8 ?* \Enjoy it5 H1 V3 S% m3 n+ D+ b
! s+ b. N7 \% x" J

: Q( T  f5 s1 e) dThat’s all!, k2 l( R6 p" b: Q
/ e2 w6 y$ L) k2 w0 h7 C
Peter , v3 D3 P9 H1 f% V
7 S7 ]8 e1 D7 h. f
[ 本帖最后由 peterhu 于 2009-7-6 16:17 编辑 ]

cmosdump.rar

3.56 KB, 下载次数: 1287

回复

使用道具 举报

 楼主| 发表于 2009-7-6 16:26:28 | 显示全部楼层
戏说BIOSKeyboard

" L7 P) S6 ?( H2 f: `; Q

& C6 ?$ b. U0 j; Z( ?8 ^1. Introduction
: n: m7 U) Q9 `% O; M
4 T% A% R( m# c. G
1 I5 k7 I5 X; b# R! G8 X" D1 [( m

- [  c  {7 [2 P8 y# O1 @Keyboard System看起来好像挺简单,但事实上它远比想象中的复杂,硬件上Keyboard System需要两颗cpu完成key stroke的转换以及和Host的通信过程,一颗用于处理keyboardmake&break过程,另一颗作为keyboard controllerhost交换信息。一次按键过程在软件的层面上也要经过多次转化才能成为最终被用户理解的ASCII码。这个过程通常需要经历ma=>mv=>set2=>Set1=>ASCIIKeyboard System的架构框图如下图1所示:
6 ^% e+ G+ M# D6 Q6 H# b! B* N
/ \* Z5 J) g  a/ G      ks1.jpg
; v( r2 W; k* ^9 D) I/ l4 E这时MB中常见的架构,在NB中这部分已经被放入EC之中成为EC的一个部分KBC,但是工作原理依旧如此。) l; i0 r: z7 f& n
& F6 u# v: l# g+ F" U( d
2. How It Works: T3 h7 W/ u2 {
, ]! ~  @# \) F$ S3 `0 |
那么当我们按下一个键,需要做哪些动作,才能让我们看到最终的字符呢?- o/ t" ~/ z0 X8 V" ~) i( h
听我慢慢道来。当我们按下一个键‘k’时(make),键盘内部的8031会将kset2 scan code2Ch
" K3 n2 c  I" ~$ ^通过上图1的串行连接送给80428042
查一张set2set1的表将该set2 scan code转成 set1的‘14h’,而且8042会引发IRQ1通知host,表示有按键事件发生。Host将会读取60Port获取set1scancode14h’,而后host会将‘14h’转化为ASCII码‘k’,当我们松开一个键时过程同按下比较像了,不过键盘内部的8031会先送‘F0h’,然后再送‘2Ch’给80428042看到‘f0h’会将Set1的‘14h’的bit7设置为194h,以表示这是一个breakHost端也会收到中断IRQ1,可是host通常不处理break codeMake&Break
$ ?9 X# K, b! N; ]1 m. T

& p9 v# P+ }7 z% A. ~* a, }key也被称之为通码和断码。最终host会将set1以及ASCII码放在BDA 之中。Host端对于键盘系统处理分为以下几类:a.字符键b.功能键c.控制d.双态键e.特殊功能键,对于这几种不同按键host处理方式也会有所不同对于c&d host会在BDA中置flag;对于a host会保存set1ASCII码在BDA之中(大小写根据控制键的flag确定);b会影响到set1的值;对于e host可能会通过中断调用相关的function# T$ K6 S' e7 N& ?! n
下图2显示host的处理流程:
8 C, r4 f$ r# d6 ]  s          ks2.JPG ' {  ~/ o* P7 l$ {, k6 s

, V5 t0 p5 u6 {3 N接下来我将分别用CASM演示BIOS处理keyboard system的大致过程代码的原理是通过hook int9接管BIOS的中断处理过程,然后读取EC6064 port获得kbcdatastatus,并转为ASCII码显示出来,有一个要注意的地方就是EOIEOI是特指8259或者8259兼容设备的中断清除指令。需要在中断服务程序结束之前向8259发送EOI指令,如果在中断程序一开始就发送EOI指令的话,中断服务程序一旦比较大,运行时间较长,可能会产生中断嵌套,严重会造成死机。如果中断服务程序结束之后还没有发送EOI指令的话,那么以后将屏蔽该IRQ以及优先级低于该IRQ的所有中断。我最初就没有送EOI,害得我调试了好久。
. O* l) |/ ^% k8 s% CC代码如下所示:
  B* V! z4 i# z1 S5 m; Q) }- U1 n3 U6 ^& B: \- j
#include <dos.h>
  Z$ ?6 V, N+ V: b- ^. A  g#include <graphics.h>
& `) z+ r. P5 j( e( X% e#include <stdlib.h>
# W6 v& E& j5 p0 `. u& |; p#include <stdio.h>
7 l, A6 D7 O6 B+ l; O! U6 A* k  _  V#include <conio.h>& H; l" x5 h& G8 ?* D) I/ D5 p
#include <bios.h>
2 Q+ J6 _+ l% }/ S& a  q) X. c
- `8 W0 ~2 o# ^0 J' y" w- R. d2 xvoid interrupt new_int9_handler(); /* interrupt prototype */+ d/ P' A9 a  Z! R
void interrupt (*old_int9_handler)(); /* interrupt function pointer */
2 ~' Y! w/ X6 k  k5 p# R7 t- Lunsigned char ESC_Press_Flag = 0;) @# G6 C) J3 X4 b6 O
unsigned char fifo[0x10]={0};2 t6 m% [# V7 f( G( _
unsigned char start=0;3 {/ R' N& ^3 w" f
unsigned char stop=0;
3 V% W- K" z7 G' I7 L4 o' I; c, o. Y
( `% L4 Z; @: n1 Uint main(void)
0 M& J2 ~/ T: \! i. X{! @0 S4 I' X+ Q7 T- R0 J
  g# p& q* K7 r, L4 }& t# F
printf(
"Used to test keyboard set1 scancode\n");
. `( A. N! H3 m0 m  r' u/ q

. A$ N5 g; ?( D7 I. F* |9 I/ V) O' Qprintf(
"@author:peterhu\t\t@Version 1.0\n");% T* E5 d/ u' a

( F; z1 e( {9 b0 Qprintf(
"Copyright(C) LGPL\t[ESC] to Quit\n");
5 Q+ _. i0 j- }8 \; p, W6 h
7 _+ y4 z5 e. ^, S# t' Q
          /* store old interrupt vector */" F7 U+ I3 m: [6 r- _6 A
$ |, c+ J* Q: v
old_int9_handler = getvect(9);

% w+ w% `  _1 ?: R3 K' s          /* set up new interrupt handler */; ~7 u* q; x0 G) g9 e
8 ?2 p$ t7 O4 `, c) b
setvect(0x09,new_int9_handler);

# C6 m0 W* p$ }3 Q# C2 X3 ?+ }( s0 v# ]2 \. j& l7 K& \$ I
          while(1)
% J1 a# Z  b& b$ |
) N: d  z  X1 i" J: \{

% \; F: N* w6 U  k                   if(ESC_Press_Flag)
* ]9 p/ z! q  w) z                             break;
8 I# B# V% B& Z6 k5 {- s. t9 [% C
% q5 n) X7 J. P6 C                   while(stop != start)2 c  j1 ]% L- r$ }8 Y5 [8 g( X9 J
# h* @+ I' h. S1 q/ M8 p
{

4 R' ^  C8 o+ ?1 q) x1 }2 J# h1 g' C( q& w
printf(
"[%.2x],",fifo[stop]);
* i- W; G' Z+ r

% |6 `( u" o# z5 k8 ]stop = (++stop)%0x10;

0 |/ S. L  m3 V! n2 O6 L5 F- [1 t& N
}
& H6 R, k& s: ~1 a# _0 E- `: ^
* I: g: O7 t! z! W% {
}

& [9 x$ {: o/ l  M  a' ^; S/ h+ N/ |  A3 N

  N3 B/ w7 I3 q3 m9 Z8 [- Bsetvect(0x09,old_int9_handler);

; W; s7 t9 q7 F7 a& K( p) u/ p& B0 i' I5 W1 [  g' j
clrscr();
+ J( B! `. O# C& P
          return 1;
4 h9 h3 [' o5 m) L# t  V}  [% Q4 A) f2 d
4 f& u# G$ F2 U
void interrupt new_int9_handler()
" X" F" _7 y: @5 I+ u" B( Z4 h{
. C1 ?+ G8 W5 X9 @  M) ?# P          unsigned char status;
( h) }- T7 B! M9 o& a7 p5 _          unsigned char set1;
( F; ^$ p4 {( o+ g' O$ }9 n+ C
% N" {; w8 b8 Cdisable();
9 Z; T8 `" C" s% ~6 a
1 t0 D7 g( Q# K8 ~, N

+ @! A. P5 l' a* ]) f1 }2 \  N9 R2 {status = inportb(0x64);
" m5 u$ Y9 w( p" ^* \9 n- j
          if(status & 0x01)6 P$ z3 ]: J& P: _0 n
9 q" }+ V6 n0 V7 X& `% E) q
{
' q- _' ?; b0 Z( N) F  y, p/ F. q6 d
. w) c0 g# f0 G3 G3 \) S2 r
set1 = inport(0x60);
, h" n/ ?$ `- C* @: }
4 n- C0 P0 D( u8 I4 J
fifo[start] = set1;
/ d- H$ k, E; |0 t) a8 ]& R
. B7 I! U8 J/ G  B8 l6 b  o
start = (++start) % 0x10;

! K  U& t( O3 C' a/ ]4 l! U$ R8 q                   if(set1 == 0x01)8 h/ t3 u+ C. [  }; M9 T
! J8 u$ {5 s+ E; Q% P
+ J# X* }0 j" U4 }
ESC_Press_Flag = 1;

( v; E% b/ ?9 Y* O; {) B7 m% p& D3 e# O1 ^& T( d
# L) j; _8 Z+ }  w! o" `' Z% v: T

" C' Z  B. j( |/ X( f+ J+ ?& G
//printf("[%.2x],",set1);

. i% n  ]( v1 @/ ^# n( C1 j
; t8 ]! P3 s6 ]' R7 j0 {+ f% b}
4 m7 x6 i/ C! q, j
5 S( V: y. l' ^. P% E7 G. G  C9 `
outportb(0x20,0x20);

9 T$ u1 i4 j. Q5 g
+ Q: S$ ^1 a* S% {' O- T
" S4 r5 A% |) m% _enable();
; l! Z5 i& Q: l, D6 I' R
}
  r; y7 r1 S1 A7 N8 l) L& y/ Z" S8 X" }% v1 S& h
ASM代码如下所示:% w4 X- d; I. I1 ^% I2 H" S2 T4 u3 `; n
data segment
( m6 c  v; z' i; a8 e. w! @
; \  c6 q; ]: A! Z, q
SET1 db 0
9 w9 h( v( X* ^
H2A   db [','0','0',']','$'
& C, f! C( V" e- v/ w
MSG  db 'Used to test keyboard set1 scancode',0Ah,0Dh,'@author:peterhu',09h,09h,'@Version  
6 M9 l, g! ?; y2 A1 e) i  R
              1.0',0Ah,0Dh,'Copyright(C) LGPL',09h,'[ESC] to Quit',0Ah,0Dh,'$'- R- g, t9 |; X, q- k. g
OLDINT9 dd 0- z! O2 |1 Z! w3 d2 S+ ~
ESCPR db 0
7 c$ K$ c( r0 k: D
5 ]# m0 p* b8 P/ Hdata ends: k& N' L( u& m5 a6 R
, z: e+ }, p! Z
code segment4 D1 I. h- Z2 m) c
  f- L+ U& v) l! U! X
assume cs:code,ds:data( g( v& x0 t- B

1 `" B9 A  n% v' @% H6 h
start:
3 N" _2 D+ B6 R- h4 S8 u

* y% `& h5 N# k& T# x7 T: w9 B( s
: Z) [$ u/ L, d; i. ]+ Q# Zmov ax,data

4 Y- y" F6 f3 z; g) r
8 E. B% _* Y+ F) T7 @2 }7 omov ds,ax

% o$ e4 Q9 V# W# j+ a4 a
) Z9 u$ D* z% n; z7 }: r) xmov ax,1ch
: w# X3 d( Q. s/ L8 g
7 j% |/ v. f$ J6 k5 W4 g
call hex2asi
- k4 L2 l- @0 [3 }) M5 {, ~- X; ?( I. N
1 c. e3 G& [5 ~, W
call show_set17 }* J. `/ F0 A& F( k6 {6 R

; r- h2 M8 s& R  n1 l* W6 ?5 xcall show_title
$ w9 i  O5 j6 V$ X+ b

7 q* S( k- e: H* U& hcall back_int9
& x* V5 o: {2 i# [
$ M1 s! r0 S) V
call install_int9' Q1 A) r/ H) u7 @$ w' U
6 t& i7 h9 Y' d4 O) H+ |5 z
l0:& }' A$ q1 N9 \- C* k# j

7 G0 o4 b) {- j# j2 _: L5 yxor cx,cx
! O7 W7 t0 j: `
: C# C' v4 H( u5 u; [# k; m
mov cl,SET1
8 j) @" o1 b; H) c' D% ]
3 J0 {, F5 Z7 D8 e
jcxz nokey

3 R/ ]0 R* F/ `  i
8 ~9 c) N5 v/ j6 u! qxor ax,ax

8 j- F% P# `- R, X( ?8 \) ~' W
2 _; l; ?, u. q7 F; Amov al,SET1

" M; `3 {6 i7 K: u) q  c% I# p# p. u, U( ]" W" m; T, p
call hex2asi

- Q" p8 q# f( r
! W- f) c! b( v5 X( B  [call show_set1
1 D# k5 C# e1 S% i6 p
2 [  V; X$ q" a3 I$ [9 J; Q/ v
mov SET1,00h
8 w! `# F) }, H6 Z

' Q8 w' E  T3 ]9 Q9 L. unokey:1 H. s9 L2 E) C( z  Z3 L

) ?7 G7 Z3 Q* P1 k& {mov cl,ESCPR
3 Q7 L+ Y0 ~" D3 j1 R
- ~1 F9 E9 S# N; Q9 n% ~
jcxz l0

! ]8 A8 S( _, E" _
1 W' ?* M9 E$ `1 C  |" a: O
call restore_int97 H+ d' T4 P2 H5 A* c6 m
# y$ H5 t: d2 Z7 k1 D* b
mov ax,4c00h6 r" `, C* ^1 x. t; m* `
/ T) q, E; H# ?  Q& g* ?6 i
int 21h
4 o( f+ f5 i. ~8 u, _
9 J' P5 }" J4 l' O! H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;& F1 x9 x6 C, q* c
;;sub routine for store and show set1 scancode
2 {+ [, X( ?- D7 d5 ?- S;;for keybord strok maybe something error :/
  @& e7 J) v( h;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
" ^8 m" p% o  M# E3 a0 Z* ^
* W0 V& ~1 x- \9 o% Wint9_handler:
- P4 u" h3 H3 l4 |- e+ A7 s. Ycli" |! L5 k% i) j$ ]0 y; d
- [3 k' N! O: ~7 M+ B4 ^
in al,64h% R( u6 i) B( e+ _- N' p0 e! p  |. O

5 X) A  p8 x% Y8 L, [% O$ _& Hand al,01h
3 p, A3 C1 o4 K' n7 Q  J0 W

0 Z1 F0 D$ V$ Ecmp al,01h

+ e( G& A. R: M
& t" c0 j% X! g# A4 }# t; ]- [: L" ujne exit9

1 b* m& e0 ~' o7 t& C" W; c2 \3 M8 ?
in al,60h

" N+ b6 O8 O3 p5 t
# i0 Y1 G0 u: k# z% p. ]- lmov ah,00h
5 w* |, |# _5 P6 \: l
" N% p. M, L  l. I+ W* e
cmp al,01h

5 O+ t" N" k0 m1 W7 O' t9 i* `' t" O1 P) ?- A9 a2 L* E
je escp
6 H$ G% `+ Y  \; H

- w; \- J8 _/ \1 E, m. E$ k# m6 Hjmp exit9
' U+ B- m: m9 G9 R

. c# P2 f  ?  q% L$ O! n; iescp:+ O1 @! `% Q( \5 E

3 J- C& M8 @4 [+ smov ESCPR,01h
' i' I: z/ G" |* o) B

4 w, x3 _" P0 k7 q+ Qexit9:' P7 z, Q1 o- q1 C2 T% t

) Y: j6 [5 N; n9 U  Kmov SET1,al

' [$ J! A7 Z% L) q9 @8 ~# a: o6 R$ @2 o; e( r& M+ c
mov al,20h
; U& b# L  [: i4 W$ X" g: ?5 z1 r& ]! ]
- S. m+ f3 |' M
out 20h,al
  B% C9 o5 E3 g1 t) _
$ i' r5 C0 u- |; [( `: D; ~! J$ f6 B
sti

+ h6 Y  l% z( n1 ?8 {( J. C% {9 ]2 B, `. r
iret
  d$ u/ H; D6 ]/ V# M
& s) T5 ]+ I7 v  v
- z" `, }' S( x7 r* [) F, W7 q8 n
back_int9:, X: ^, m, _. J. F5 M9 p
' U+ c2 w! g! Q
' i: e% p9 D5 }4 v: d8 k
push ax0 w/ ^. q6 b+ o  m" U6 Q: J- |8 U: E
" P- S7 y- ~7 |( S: c8 r0 x3 [$ A
xor ax,ax
, ]  X5 M6 e2 H( [% I+ o  S
  J( M1 f" M  r1 h8 kmov es,ax

5 S% u9 C/ }% M( d: t# U/ _0 v) Q8 g! C. ?* i
mov ax,es:[24h]
% B1 r0 ^$ f) B+ U  r; \9 {$ [
  d9 ^" T9 ]) B) N! o( }' `% P
mov word ptr OLDINT9,ax

+ ]" g% ?% v, P  Q4 v/ B
( p' ~; D3 \8 ?1 B" b) }$ Bmov ax,es:[26h]

9 y! [  H, t8 a4 z% x
9 O- b; b0 G1 Z& d3 Bmov word ptr OLDINT9+2,ax

0 s* T$ t2 ^5 u- ~+ I' @* G3 S5 P% n- E5 Q% ~/ C6 }
pop ax
3 e$ `6 x3 ~/ y& ?* ^
2 C9 o0 \3 x% K* A
ret
* G/ \: v. k, S  T- q

$ e% ~& Z$ m. s" ~0 `& `restore_int9:( _; M6 t6 A/ E3 v1 z4 N( A7 H. q
% S- ]4 k/ b* Z7 x+ F3 l4 M
7 G1 C/ e. b% p8 i- E
push ax
# m, ]9 ]+ @: S2 `4 G3 _, r

1 ]  H# I& i# i4 t/ \5 bxor ax,ax
# q, H6 X7 R3 e6 R

) q2 R+ K3 V% `5 T4 s1 {mov es,ax
. Q1 U+ r: G, v- ^6 l/ e
2 g5 U& x: _) N
mov ax,es:[24h]

, q+ h: C, \) O  E9 c  y/ u7 n$ ^5 R; [4 H8 v
mov ax,word ptr OLDINT9

9 [. U9 L( p: b9 I/ I6 t! U" G; n$ m
mov ax,es:[26h]

- M2 a, H; R- F) v5 W2 @8 O
( o6 A, s( p" u: Z+ P4 \mov ax,word ptr OLDINT9+2
6 l; r: y) b, l. l8 L  O# b
" b6 R  _; G8 g$ z9 F. x6 Y2 d" j* |3 R
pop ax

* A3 G* ^  X' ]% }" O+ t  i# D
) ^1 t! t0 b, a- P, M/ yret
4 v) j& d, _* G+ p' `; F/ q$ m
3 M% N* O6 F9 m0 c
install_int9:; z& h5 l; m1 _. L' k

" f/ [! G; r9 `/ S* R& ]) Y7 m6 Gpush ax
4 x4 j, [( D; n& o  _

  U  H" o- H; \8 x* O9 x5 Mpush ds
, k7 ^" ]# E# G. O

9 s$ Y0 c3 A( o  a( Bpush bx

6 K! V; L& H8 X! X
; z  i4 o+ w# k2 ?. ]: b4 u
mov ax,0
/ g3 V+ u& Z) u2 k4 e7 h7 F( W( i5 R, Y, F# r9 B
mov ds,ax

/ E  L1 b2 [% P2 k3 C
# T( l2 L8 A! s& t' h! Kmov bx,24h

( u8 k- D# X8 s% v
9 u) W  X5 _* D/ s8 Ncli
/ L/ c8 `9 Y3 T, e

- x* ^/ ]& r) W" L$ j( Z- hmov word ptr[bx],offset int9_handler
) ^4 z% I, w& i! A2 e7 j
- G% h2 T7 ]8 F; Y: i7 p: ]mov word ptr[bx+2],seg int9_handler
3 E$ e1 L8 [' F/ X

" y( H# n$ i6 U  ksti
' f* \/ `% }' c( U9 F; u; T$ T

0 W) s4 K* ?4 g2 q& P4 Y8 Jpop bx
4 S- |& U# ^$ L; \. R

9 k4 T9 {- J4 t: z0 rpop ds
% S- P2 q- p' B) l. \, S

# ~; w! @6 n7 l% a% Npop ax

) k9 a/ R0 q* @8 D8 o& T; e. Q8 F1 a. F3 u8 M
ret
6 |! P+ |8 X0 k; |# Z

* C1 \: |" ]/ ^/ _show_title:
" A) R& a0 G8 e$ g$ h$ u  N/ ^  P5 @# \" Q! O' R, Y- o. d
push dx
' U1 `  X% v- B6 o6 C; H

/ A# A' @/ f* z) ^mov dx,offset MSG

9 g& q) i4 \8 q. B
+ s  p9 Q" _9 z/ ]  Xmov ah,9
" o# C: |. Y# |) z2 n! {

3 A; k8 @0 l: L( p& Rint 21h
+ D/ D/ o0 {, ^) k3 ~' Q/ T$ H7 R

2 p' t5 Q7 h/ ~/ Apop dx
4 W" V& N' w+ {% T. ^( L

- e" \/ U) F0 T# jret
+ s/ {% D$ ?* y* F2 P0 `) Q

  r( m' l, v' H. wshow_set1:
$ c4 x$ _; e- ?+ s: j  |9 h
9 S! m' W0 T1 hpush
dx
' x, i- s* D2 N7 W( K& ?: V3 F
) E& w/ y4 p$ a2 Dmov dx,offset H2A
7 C/ i- D& t/ A+ R. K( v
) _) c$ w- T: }9 W- Z3 S* w
mov ah,9

! \  y# {1 D1 ~( G- C+ u! Q, [) m! L
int 21h
# @1 ~+ T1 m% o+ g
& ^1 A& A* L+ K
pop dx
4 o: V5 G4 i8 l& y, x" E2 f0 j2 W8 m
: m  a' c) Z* N8 H$ _
ret

/ T0 y) ]2 X+ o0 a
0 E/ g, F/ T9 s
) a! W: d! K  `& U# h' `
hex2asi:  u# H  d# y# [' e
+ P4 R! m& S( H3 P# l
push dx

; i9 e9 ?1 _. H7 ?+ X) V0 [$ ~- |
5 p8 R' u' f: P5 J2 b7 _push cx, `# S" U( Z  M( r$ e4 N# c

; F3 F1 m  m" t7 z& z, G8 I, Tpush si
, A" N$ t- J( g; M) g
( W0 r3 W' W2 g8 q) W7 \
push bx
" |3 J8 x+ p  k; \* O: u& l% {

! U+ {; Y0 b  zmov bx,0
1 f0 Z( ?+ j6 D- O3 L" e# H
( m, B$ }" D' v$ c, \( |/ [
mov si,offset H2A
, @- I7 m  K/ Y0 I1 Y$ {& `
+ U, n. Z* [# k' W
mov byte ptr [si+1],'0'
$ o2 J0 z1 ~( C9 Q% _
0 K" |. M7 {- B) L# u6 a
mov byte ptr [si+2],'0'

$ v% e. X% e* O) g  E5 j" N5 I6 j
ha1:
' e! x7 J3 Z  J
; }& n% q2 _: v8 q3 Pmov cx,10h

. F* J, e7 L% y# ^/ E5 g+ P& r7 {
; h. h( H: F9 Hmov dx,0
' \3 K# R4 Z7 _8 g5 k! j/ _
" R5 q9 X% H4 k
div cx

& W$ Y; c7 m. y* p" r! B
5 p& k- N3 n  V6 a) Wmov cx,ax

- D1 h) f0 f, @% m8 `6 `+ P# z2 J4 o$ O
jcxz ha3

, s+ d( D, G% O. `, ?4 C  Z
, R! W% c/ E! c' v8 tcmp dx,10d
: J- Z! |$ z) G* C

, q' m. {+ a# a7 j4 Ajnb ha2# H. I# {2 S8 r$ x% K

; N* h# W) b) ]3 T2 P- Qadd dx,30h
3 G9 [9 P9 o8 w  v8 t2 P* `! A% F; I& F& H) n
push dx

) H8 X2 R$ Q& j6 J" N4 R# J
' Y. _" H, t$ y; A3 T0 J) J5 Jinc bx

2 |/ g6 q1 X8 q4 f9 \* V8 }/ Z5 `, t6 r
jmp short ha1
. H- P) s: \; V& R" K. k- Y* ?8 q- b2 ~
3 S' l' M$ o7 r" `+ d- R; O5 [
ha2:: S* y# w! E4 f9 ]) c

" W2 }$ e) {! f* I0 m8 `sub dx,10d
4 [: z$ w/ U+ j7 c( q5 t8 {7 i
5 x. s; A6 N7 {
add dx,'A'

( I; @$ T# U) Y: o. ]" a1 k8 R& D5 D( h& F7 r% G) H: s; L
push dx
' k+ q9 O: s, `4 o8 r+ O/ J  B
6 F1 C! |2 n0 F; Q* N+ i8 ~
inc bx

/ F4 B& x) ^2 D4 i+ i
; ]* G5 @/ q* _9 N4 J3 B/ X: i5 ejmp ha18 a$ v% ~$ Z) q+ o: u/ p3 B

# U8 V3 a# |/ J" E" w( Hha3:
  N& \( C: U+ Y6 O8 P( g/ O& I& M3 t( P
cmp dx,10d
# H3 I. u7 m" f% Z, H. }7 c3 [3 C+ |

% c3 ?2 F, ^4 h4 d: \jnb ha4

4 I) `( g* Z" z/ Q  ?
+ G$ O$ N+ S& ~. uadd dx,30h

4 |/ @& A* }: R1 f$ o
3 }) B% C+ t: ]" a! c+ j. Gpush dx

7 h1 Y9 W2 s$ u1 Y9 f" r( ~( N! w1 G2 J' k4 v9 X- z" g0 q2 p
inc bx
4 p* r5 i( P- `; t( e& E
+ t$ X: ^7 G6 @4 T1 H; t
mov cx,bx
# Q0 v! l4 n; H0 T- Z$ C% s1 k
7 V$ F  W1 e) q2 N; l* ^
jmp ha5

% J' e5 S0 s# [, K4 f: l3 A. f4 W, `
ha4:
1 p: E, z" F- m( D  a3 H- r& ?
3 Q" B% v6 {1 o" z( \: U0 M
sub dx,10d
; h# F0 Y: ~' @$ `; B' d& a" o
) `# i$ f5 t- }+ H1 ]3 z+ |3 q
add dx,'A'

2 Y' |& ^' c& Y+ A0 {% z
8 K) P( |4 P0 Vpush dx

& w8 y1 \* k- D6 ?" ?3 N/ _! y/ p! G- ?" t
inc bx

( y# n6 E% r: \, |( W8 B! c" ]8 L) X2 J
mov cx,bx
* s- l: b, B$ T! n7 E
& i1 Z2 ^5 U" I3 t
jmp ha5

3 [" I5 m8 ^7 |( o, Z/ i
# B4 K8 A3 e: |6 C/ Kha5:* S- f7 Y- l; \" f
pop4 R5 c+ L0 o9 z: M% B0 h. ^
ax
9 x( d: K: F, f4 \

% q. S; v6 F! `4 x9 @mov [si+1],al
* R  i2 a7 y# S. A# M/ a: w

. M4 r: H4 D) O/ @- o5 r5 e4 [1 Q$ [inc si

# M, d+ n" M  a% B
1 B. k0 b" e# }" T" K8 S: ^loop s4
  _" R' y6 @3 h: Y& Q
; ]# r, V4 S7 M
ok:
+ y# b, c1 \4 A4 @- m: y
2 j' b; S- l0 z. j: `9 zpop bx
7 F+ U$ u* _9 I& a5 m* Q" K2 @
2 \6 A1 U' l( m0 c' S8 M7 [* p
pop si

! t' G) T. c( U1 S+ ^: f. G$ {' A( X% z
pop cx

% R/ o. l/ m! v4 Z9 V: {& y/ n. k' G
  i( W' Q7 a: T. ypop dx
5 K/ i3 \7 j4 L) U6 z8 h3 g

; Q- V/ L. k9 D, L6 b( L- h$ ?9 ?ret
2 d# m8 U: i  A$ q, h2 P" m1 r
- x" u# Y$ I2 s

- X& Y4 T9 y. o2 S. p# Ucode ends
2 F! c) R" T, E: T* zend start, Z/ G& X- P& a; b8 _
上述程序运行状况如下图3所示,一旦有按键动作该程序就会显示set1scancode(没有给出相应的ASCII码,凑合着用吧J)上述代码可以在附件下载. k/ K$ _9 F1 T& F9 m' F+ w& i

" _/ C' [( s  l# X) q# Q1 k( i$ K3 q( q5 m% \6 M- s. t4 J9 X
ks3.JPG
9 G5 ^1 c! \' _REFF:
/ ~; m6 D) d. j& y1 n<<The Undocumented PC>>' C6 g- D, r/ y/ y: N7 w
6 l. R4 z' B3 m
Enjoy it!! p, F+ W6 q, H$ L( c( V
That’s all
2 s' x  {5 j4 \. [
$ y- t) T* {+ S! B* b1 y- @Peter : b/ D6 G, V; i. Q6 u$ j2 b- K" V! E

* W% B( }8 U; f[ 本帖最后由 peterhu 于 2009-7-6 16:36 编辑 ]

KeyboardTest.rar

2.07 KB, 下载次数: 1307

回复

使用道具 举报

 楼主| 发表于 2009-7-6 16:41:36 | 显示全部楼层
戏说BIOSBeep
4 X7 F2 G! g% \. q) a( Y

( m- E+ S: H4 D$ n7 x& E1. Introduction: x6 ?% ~# U7 [; `

3 I/ J9 S* G& [大凡用过电脑的朋友都应该听到过BIOS的报警声,有时PC开机的时候就会听到嘀的一声,有过修理PC经验的话就更清楚了“一短内存刷新失败,二短内存校验错误,一长三短内存错误,一长八短显示错误”等等诸如此类,可能各家的BIOS定的规则不同,但目的都是通过报警音获悉系统运行状况,找出病灶对症下药(有点像中医诊断中“望闻问切”中的闻J)。
* M) Y0 U8 |" [; g
9 _+ P$ G$ S) t) t7 T( K& @) q
2. 8253/8254
) x  X3 y( ?! W7 R
* }  o* ?1 V& N# x' UBeep声我们都听过,但是有没有想过这是怎么实现的呢?带着疑惑随我开始探索之旅。提到这个Beep,它可算是历史悠久了,追溯到IBM的第一台PC那时工程师们可能觉得pc功能太过单调枯燥,于是他们就祈求上帝给我点声音吧,于是声音就有了J。他们将一个简单的扬声器加入了最初的pc硬件之中。光有speaker肯定是不足以产生音乐的,因为音乐得有音调和节奏才能组成。虽然我不懂音乐,但是我知道一点就是声音的高低和频率有关,所以还要有能制造频率的东东这就是8253/8254。既然提到我就大致的讲讲8253/
82548253/8254是可编程的定时器,82548253的增强版本差异主要在可以外接clock频率不同,其实使用上无差了。8253有三个独立工作16位的计数器t0t1t2分别使用40h41h42h port去操纵,除此之外还有一个43h port用于设定控制字。三个计数器分别编程,但是在使用之前必须先配置控制字,控制字主要用于选定哪一个计数器,选择计数器的工作模式等。控制字的格式如下表1所示:
7 \8 s: R- A/ F/ k( h7 a* A1 ^0 K7 x/ ~
Bit 0
# r# Z) ^# m% \4 v) J
计数值格式 0表示binary1表示bcd3 `0 Z1 ~  w5 ?/ k
Bit1~3) I  j9 Q) A% N
模式选择  r: O* l( a' F/ i& @
Bit4~5
0 Q8 R/ n4 W4 I& j" @8 }/ V( j$ _
读写指示9 P! N- }8 m2 Q: ?  s
Bit6~7: V( u- n, Y5 F$ c8 U' a* y3 p
选择计数器2 ~% k2 @' r3 D; l* r& s# \+ S

9 \% R( m8 p+ h) ]1 M9 b             表 1
6 N& K+ J' |+ B/ a: [% z! E! x
5 U/ r/ u5 h- u5 e
其实这三个计数器在PC内部已经规划好了功能,基本上不需要用户参与了J5 N8 Q/ a) o; c7 C; B
t0:用于系统时钟提供定时基准,它的输出端与中断控制器的IRQ0相连。
8 s! x: K$ F% ?- p7 }t1:用于DRAM更新的信号,每隔15.2us刷新一次。6 a, g3 c# I3 Q" f5 M+ L' e
t2:用于控制扬声器发声,作为speaker的音频频率。
% c' {/ ^' L) J, O1 F所以我们知道t2用于提供speaker的音频频率,驱动speaker发生。这个部分早期驱动电路如下图1所示:) p( `5 K! A% `

9 o& e- H- B: O! a
3 J7 B) W# g" T5 `' x/ i Beep1.JPG
( }  ]2 d6 k5 s3 r# g
由上图1我们可以看到61h PB0控制T2gate2,也就说只有将PB0 pull high T2才能工作。另外PB1T2的输出端OUT2经过一个与门运算然后再驱动speaker,所以PB1也要pull high这样T2的输出就可以操纵speaker频率了。图中的61h是没有介绍过的,那就再来聊聊61h port61hXT系统中集成在8255之中,8255是一颗可编程的外围接口芯片,61h对应8255port B,它是一个8 bit IO port,每一个bit代表的意义如下表2所示:
" W1 u  X9 G; n3 c
4 q) C. R4 s# T$ C4 b1 Y$ e4 I3 j
Bit0
1 F) @+ y, r# c% Z) |$ c) {& Y
t2 gate2 控制位7 D3 d( y+ ~3 T8 M

% t8 |( `1 [" N# _& ?, p
Bit1& i0 ]- i7 T) A
Speaker 控制位
* a2 o) K4 J2 _( L+ p
Bit2
6 f9 G  M/ M8 ?" P) X
DIP相关
/ T6 s0 t; J5 w) p
Bit3- e* i- D# ~6 `* q6 `+ \3 s  W- j
录音马达
5 A9 O' ^- a% @% M% c7 Z7 P# h: r
Bit46 n* `5 p: G9 }5 \/ J# U9 n$ i
RAM同步更新检查位
- o; N7 W& l2 y8 G: X8 K/ a4 c
Bit53 ?- D4 W2 P, W' t: u; g7 {3 U9 s7 j
I/0通道检查8 H$ \" r: W1 H) G
Bit6; {# B- S- s4 M# i; K4 T* r
Keyboard 电平控制
4 x7 y3 e, I& C. d: |5 v
Bit70 R4 D  i3 W$ S' p
Keyboard 始能控制% _$ r2 Q3 g* u; j1 F
$ s3 q2 W* n4 l1 S
             表 2
3 b  L7 i5 Y. `( Q
AT以后8255已不再使用,port61h也使用别的IC代替了但是它的主要的bit功能还是保留了下来,所以仍然可以使用I/O指令读写61h port. s- I, A) j: O" x/ e2 `5 ~$ C6 r6 o
# t8 }: G# U+ n" X! u6 y
3. Beep~~~~~~
: Z0 z9 e6 Z3 M) {/ g/ c. u  l  B3 e" T2 R) q% C
知道了以上的知识,我们就来写一个“一长三短的内存错误”的报警声玩玩咯J。需要做的工作有三个:a.通过操作61h port始能speaker inputt2
gate2b.操作8253控制beep音的音调;c. 音调保持一定的时间(也就是声音的长短)。我们逐个的实现上述功能。
$ n! I$ F0 f8 K! v+ ra最简单只要将61h portbit0&1 pull high/low即可始能或者禁能,代码如下所示:# \7 w8 z. \& W6 B* K. x
;----------------------------------------------------------------------------
3 R: o& H" p  P: T: d' j# W8 J( ~% R9 g

: |/ `( x+ r4 |0 |8 y& q% i* r;speak_set
7 {' Q  `7 w- C/ X# m( I# \;en/dis speaker input control&t2 gate2 control9 M, \3 v& A: ]8 k5 F, U
;called with:cx; y0 S( J& O+ T- Y$ x
;used registers: ax
+ X* d& ~6 F) s" y% y" B;-----------------------------------------------------------------------------" T' q9 H+ j+ A* h0 x: m
speak_set proc near
) E* j  ~8 e4 j7 Z* p/ c4 J* s* s; r( H$ O
push ax; A& }& _5 e8 y; F# H

, x$ j# H$ X0 `4 B) j4 D! Iin al,61h

8 t* J* B8 _# R0 P. V& c# W+ y' ?* k
jcxz se_d

( r) g  ?5 i) |; X: O2 N. p6 D6 r
5 @) q  h, `3 }* {1 q& Jjmp se_e
  k8 ~$ V( x1 u) z' s  \
* _% `5 ^& t/ j5 C0 |8 v5 Y1 Z
ss_d:
, f$ k; N( I9 _0 ?. Q5 L0 T8 K  {# T. o7 D* T
and al,0fch
2 P3 M) x5 K% R( w% U) N
- V8 J- {; \2 P% }# O: |, ~
jmp se_done

% z* e% b4 V+ Q, L/ f" v6 J# o$ e; T; f
ss_e:
! q5 V( |6 Z  m8 j5 w$ X. t4 G
7 p6 k: C. _* E- ~7 [or al,03h

2 N" l) J0 u+ |' n; w' W
4 @, Y0 B5 y$ Q+ v1 _1 s, Pss_done:
4 v1 S3 T+ X* \2 ~7 v8 L+ }
) Y0 Y+ r+ Q% F( k/ Uout 61h,al
% j) W' @% `3 g/ \3 m
1 B5 y# E- V% G* W8 s% ]! T" F
pop ax2 E% v- z9 l6 {; O9 B9 F: F
1 |$ g2 s4 q$ g; p0 p9 B! l
ret

+ G4 u( p8 j3 W5 z% V* z, e5 n
0 }* w: M0 G- L0 W4 o: Wspeak_set endp
8 Y/ o* y. X# J

) F6 C. v. V/ O, {& T/ l+ g, g  E( G- c0 z5 P7 M* |3 Z/ e
b就需要设置8253计数器2的模式工作频率,操纵8253的步骤为先向43h port选择所要使用的计数器以及工作模式参数类型等,然后再向42h port装入t2的计数初始值,代码如下所示:
  K8 x! j6 G# u2 E$ X4 O4 E/ Y;----------------------------------------------------------------------------
8 k% C$ A0 a4 W# k5 p6 R$ x  g
; m' {4 H" w$ m5 m
;t2_set: E& Q* U, u7 ~, V! J
;enable t2 & set work mode & out 2 frequency 0 Q7 j& L' r1 T1 A( e0 R
;called with:di(frequency demanded)
- d5 H) B6 @% z7 U7 r) f' p;used registers:ax,dx, p; U+ t. g. ?$ k8 u' R
;-----------------------------------------------------------------------------$ g: Q% G  g$ t. P6 N
t2_set proc near
" b5 ?  T1 b+ m6 \1 A/ `) U! |- U8 q' f/ |
push dx
1 G, p; r: w; F$ y( }) U8 y5 q  P
& N- G' z; |/ C; [push ax

# I4 c1 V1 T* X; J% L9 v5 l. f; u5 f4 C4 {# H  i- ~
mov al,0b6h ;t2 lsb,msb,mode 3,binary

7 ~9 q  n4 m" `8 {" ]; C& K6 B" l8 j3 g1 p- k9 |4 {/ Q
out 42h,al
) E7 l; N# C8 q+ L9 I
9 |2 l6 o: {" `( L3 k9 h* _0 O- b
mov dx,12h

( |& l/ g' f  c! J8 C* l1 l5 M! D
% a; J* t9 a0 }3 w5 Imov ax,348ch
- `5 K  V" V* e, D
% L* O# k/ m7 z2 `3 z  |
div di

0 E' V, `7 A) V# E6 Z7 c' L, p
' V: G+ }' U- uout 42h,al
5 L# H; e$ x7 R, l6 k8 }
# B# s/ q- Q0 f$ O0 a7 w3 U
mov al,ah

0 i" ~+ l5 H  M( n
, o1 W9 o8 i- q5 pout 42h,al

1 k  k3 }. ]# g1 }6 C  B7 O% [
( @3 M: S, z, u
pop ax& U) N8 L* R: a4 E2 r- l
8 C  {8 r: P6 \* W0 J  l* j
pop dx
7 x% L! i' j" S
* C* ]4 Z0 B* T% ~9 J
ret

; g, v( ?( `: C
7 \6 x+ M" x) ~# bt2_set endp7 \& L$ s/ y/ q' D
7 g) N! ?: v& Q6 x7 H" u- Y$ _
c可以通过执行loop达到延时的目的,可是loop延时和处理器的类型频率有关,不同种类的cpu执行同样指令所需的时钟周期不同,就算相同种类但是主频不同的cpu要达到同样的延时效果计数的基准也会不同。那么有没有精确延时的方法呢?书上给出的答案是通过检测61h portbit4 ram刷新检查位,每隔15usbit会发生一次变化,所以检测它可以获得比较精确的时间(我猜测这个bit会和8253 t1同步变化,因为t1的输出脉冲用作DRAM的刷新定时信号,而该信号要求15us刷新一次)。延时的代码如下所示:& _) [3 j2 @2 q) a
;----------------------------------------------------------------------------
$ f$ y* U6 {# a9 e9 g7 H

1 O. S$ T' X% v: i5 M;delay
6 T5 \: ^3 Z, n7 [, Q$ p;delay time base on 15us unit
2 x* ?  v5 g# q5 L* l: ^; u;called with:cx (counts of time unit)4 s9 }9 h: V! C! z* @
;used registers:ax3 T- w# s. T0 p* `3 H
;-----------------------------------------------------------------------------
: u2 F& A  f. H/ r1 vdelay proc near5 a  P5 m4 \1 \" N( T  K  V- G
9 ?( |  e! e( w2 X# A
push ax
+ c$ G& q0 q  Q. Z; x1 c7 }- r! }; T3 \% u
dloop:
: V" V: O6 [6 w. S! g. i5 e$ k1 C. t; ]' ~
in al,61h

. k  g5 ?  O/ ]- f, K) |% M; v# A) K( e* K6 p8 a
and al,10h
5 Y6 I: m# c, ^. C5 a7 s
8 o& Q: E9 y9 y. w% P$ H; A
cmp al,ah
6 w5 z' t* @$ H
5 e2 b6 g+ b! a# A) l
je dloop

) b/ |" b2 C6 R2 c6 E, c7 X/ \: n
: y  f$ a3 z: ^) p% Nmov ah,al
$ r  }" M/ t, L5 \+ \1 I
  H' W! t+ \. n& O+ A! L
loop dloop
$ e, T! ]# L; ]7 ]

2 D! P5 r5 [3 P0 L% qpop ax

8 |. n* C. n' c5 K! k+ W- l3 r( O+ @/ @* O& @9 Q& c
ret

& Q; n; o; r, g6 l: k3 p+ v: m8 V+ G" @6 a* v" M
delay endp/ _3 |8 [! n+ b3 {. o
% Z8 ?% l, h# e- }; x& h8 f  n
以上就是beep的主要代码了,最后开放完整的source code供有兴趣的朋友参考。& Q; s; O0 r# w4 d, d3 a8 T
+ V) w" |4 G2 Y* K9 y( z) P
REFF:
8 C# C) @7 G& F" n: t+ H4 Q% f& s* _; R0 ?6 n

" x% K4 D" ^6 Q- q2 |1 D" s
PC硬體元件控制詳解! I, S7 ?2 K0 C) X4 h: D  v' l1 u

2 k2 _# X  C0 MIBM-PC汇编语言程序设计》
" Y" {+ b4 H7 \  v; M

* i4 h* R4 C& |/ e. d  n* T' R% T& Q* h- P# n0 W

* _0 Z- ^" d9 n/ jEnjoy it1 q6 \: C9 T0 V" k! o) s

: F" U. W6 E2 S% D6 N# I" e3 Q$ y5 m, ^5 r6 d
That’s all!- l+ O5 z7 [0 e1 m
! h6 Z8 Y4 j  n/ G6 t- K- P
Peter
2 a, A! E. k) P- X
. P) h- n( B" r+ q5 v[ 本帖最后由 peterhu 于 2009-7-6 16:47 编辑 ]

beep.rar

945 Bytes, 下载次数: 1282

回复

使用道具 举报

 楼主| 发表于 2009-7-6 16:50:33 | 显示全部楼层
戏说BIOSPCI Scan
5 r; {6 U/ m' M. z

7 r3 Q. @: [0 E$ p& r3 h# w2 _. o% D1. Introduction% L9 h# z5 z% ?9 o. Z" G( o

. n2 l+ V' g! j$ k  `" CPCIintel公司在1990年前后开发的,后续经过若干年的发展以及标准化,它已然成为server&pc上的标准总线。PCI以其出色的设计以及不错的通信速率在计算机领域攻城掠地,不断的取代诸如:
MCA,ISA,
# E' t/ i1 @. f: q1 g0 YEISA,VESA,NuBus等传统总线。PCI相对于传统总线有非常多的优点,如:1.它是数据总线和地址总线是分时复用的,这样减少了pin脚节省了空间,而且这样也可以方便实现突发式数据传输。2.它是即插即用的(plug & play),当device插入系统时,系统会自动对device进行资源分配并加载对应driver,而传统的ISA device则需要做复杂的手工配置。3.中断共享,传统的总线有一个致命的缺陷就是它们是中断独占的,本来系统的中断就非常紧缺所以增加新的device会出现中断不够使用的麻烦,而pci irq routing机制使得不同的device irq共用成为现实。可是技术的发展总是长江后浪推前浪,前浪死在沙滩上J! PCI又逐渐被更好的总线PCIE所取代渐渐退出PC的历史舞台,后续我会再去研究一下PCIE
- w0 F# J9 A+ a2 Z! }; O- X
( E7 ?3 y. @/ d$ U" R* W2. PCI Arch8 N( k  g2 D% u# a
. D4 p+ X, }$ B0 i
可能是软体背景的原因,因此我看PCI spec也会习惯性的使用软件设计的视角去理解PCI的设计(我觉得有关设计、架构的理论应该是相通的,正如软件中经典的design pattern的思想来源于建筑学一样)。我的视角里PCI同经典的接口编程或者插件式设计非常接近。接口本质上是一组规则的集合它是对同类事物行为上的表示,它的主要目标是实现相同类别的不同对象行为上的多态性。面向接口的编程是OO思想的精髓所在。它的好处体现在哪里呢?首先它增强了系统的灵活性,只要遵循接口定义的规则,系统的底层实现部分就可以灵活的替换、扩充如:PCI总线定出了设备的统一的硬件接口,这样遵循该接口pci device就可以方便的扩展入系统;另外相同的接口可以接入不同厂家的设备就像同样的sata接口可以接三星的光驱也可以接LG的。其次规则给出以后,实现该接口的部件就会有共通的接口但是不同的实现,如此系统端就可以通过接口灵活实现对部件的操作配置。PCI定义出了三种规格的配置空间,根据配置空间提供的信息系统端可以方便的识别设备的种类,功能甚至于厂商和版本号,获得非常丰富的系统端知识;而且该功能也使得设备可以动态的配置资源进而能够做到plug & play

! a2 j3 g! F$ `/ E. {, H# D6 h) d4 `# _# g% X! ~
3. PCI Scan! J. Z( _9 K, t6 e2 y/ E7 D

$ U5 A5 w3 L/ n# R1 W2 {8 A9 w
; z$ z- a, S$ U3 uPCI Configuration Space是大小为256字节的一块空间,它由headerdevice specific两个部分组成,其中header部分是固定的而device specific
部分则是与device相关的,不同的device会有不同的layout。配置空间被用于配置,初始化以及灾难性错误处理的功能。下图1type 00h Configuration Space Header
1 ~. s6 X* M4 P  i! c) t% a; E
' P( Z" @* p' F) C7 E/ E$ [( O' l+ q pci1.JPG + h, w6 P9 C% h  r. @" L
  Q& U3 s2 ^( A. u2 }
1
0 o: B* N7 i6 \' n2 z+ |
PCI Scan的重要任务就是读出该256bytes 配置空间,那么如何读取这部分的信息呢? 有下述两种方法:) e( t7 o1 r) z: z) }5 y' U
1.使用0CF8-0CFB, 0CFC这两组IO port存取PCI Configuration Space总线号、设备号、功能号和寄存器号组合成一个双字送到配置地址端口(CF8H-CFBH),然后读写配置数据端口 (CFCH)即可获得配置空间的数据,下图2是配置地址寄存器的格式定义:. }! O3 S* K& m1 Z* @2 F( |
3 T7 z  Q8 N  I) d1 V8 H& p
pci2.JPG
2 V8 K# I& R: I& Y1 g
! r% k  C: u! r  |+ u( c2
& r5 w  n: {. u# Y3 n* C( m
所以我们先要build一个config-address然后再去透过端口存取配置空间。
* [% N* o; Y" O0 {* D下述代码用于build config-address
& K! h+ F: h- e;----------------------------------------------------------------------------. B: z5 J% _5 J, V7 H
;build _pci_cfg_add:. V4 o+ @3 |6 V$ s) N( s
;build pci config address2 M( Q8 R4 j; H9 s" R( B
;used registers:eax,ebx1 M7 C. V7 v; \8 B
;-----------------------------------------------------------------------------
0 v' k% m1 N$ @build_pci_cfg_add proc near
) s- [  D  B; D! w) [* A
: ]- R% G5 Z- v* ipush eax

9 c$ _" [7 a4 a% a2 L8 R! Q6 S: H' K) O" f. e9 f: g5 F+ K2 [. ?; M7 z
push ebx

, M9 X, V4 F1 R/ T
0 ^* w( o. j1 R1 v' o% ]# @. fxor eax,eax
7 C$ o9 @( J1 S3 A& _, C
% i( X: m& k% J* n) u+ A$ P# U) exor ebx,ebx
7 X4 q- b. O1 S" t
; W/ P; p$ h( V
mov PCI_CFG_ADDRESS,80000000h
9 f; H( J0 p% a- w

% e; j% y) Z- T1 W% ^+ n1 D, y+ umov al,PCI_BUS_NUM
: m- |) F( u6 Z! K' m
6 d/ |: ^" ~  E
shl ax,08h
  S" [& X3 P+ I, }' ]& ^7 X+ L5 N
  q& q8 r, }# b  l- o
mov bl,PCI_DEV_NUM
( u" o% v* r( V1 r. Q& u, {

6 h5 m/ A: e5 e. O8 w8 qshl bx,03h

+ E% A1 e+ C9 P9 f3 y9 Q+ t' r
% G; O2 |. f' _7 {: P5 _or ax,bx

, \: y5 i$ A  x# w* ~9 C3 M; I  ^* f: X3 u1 v" ^/ W
or al,PCI_FUN_NUM
+ K+ G' ~, E9 O6 I# `" e8 `
! z- d, K+ x* E# R6 Y
8 O5 |3 D0 z) i9 x, Q
shl eax,08h
) H: o& t  P* O" a2 ?7 g, m

! @$ a4 m4 K9 n% G9 gor PCI_CFG_ADDRESS,eax

) O: L6 [' \, [  f3 R  R" y& S2 N9 `2 o9 l* S  T: d
pop ebx
* k5 D, m; h5 a$ x" r4 A! Z5 Q
) k1 C' Y8 u& `- u% ~" Upop eax
( C& ]  l1 s$ R! D( }" T

, o4 W3 D8 s' A* x& k" [- oret
$ ?" v4 s" }9 D- K

$ A( d) D; `2 D+ @" d) K" ebuild_pci_cfg_add endp! V9 X) D  o6 }) A- ~2 i1 p% d& R; b
% H, ?( U8 c# K# Q6 z* l2 A

- H* A% J& I( i. G* }! x$ c" Wconfig-address准备好以后接下来就是透过IO port读取pci configuration space了,下述代码演示读取的过程:: Z4 a% {# H& a. u' ^2 a' c5 {
;----------------------------------------------------------------------------
: u8 @3 u7 f7 p3 |
;read_cfg_space
; l- T) v: ?6 u& J3 o8 o" D; u;read pci config space use io port8 {  t. W( v4 Z" h( ~7 I$ r
;Called with:NULL- {6 y5 a, C) h  n3 {) k2 w
;used registers:eax,edx- f' p! w& h" T. o; [
;returned regs:eax
6 g0 O& U8 t/ v5 [9 n  s% t;-----------------------------------------------------------------------------
# V5 ]5 ~: I6 X9 O1 iread_cfg_space proc near/ x' K* R- a: v

. u7 d# o2 }  T" mmov eax,PCI_CFG_ADDRESS

& ]' M/ n' n- a" i3 f( X) r  K2 _# q+ N/ _5 w6 Z0 t$ u4 J4 G
or eax,edx

/ c) H0 s0 U* u$ w
9 E1 x- i, d: {1 X% k9 dmov dx,PCI_CFG_APORT

  o( ]; \  x' f* |: J, N
+ S( h5 M' j8 U: Kout dx,eax
+ T; g2 t( ]3 ?

3 B9 V; L( r* M& I3 |& D" B9 kmov dx,PCI_CFG_DPORT
. Z' O4 q7 o! x/ m5 J; ^
* l! h2 _7 P( `# s
in eax,dx
$ ]- i& T4 i. A& j" k7 t

7 D+ L- k6 y/ l$ v0 }" cret
/ z) R; j" d9 \& P

! b7 {4 T8 c" o5 B" oread_cfg_space endp0 ]1 ?) l. d5 c% ]# o. k* I$ |& R! L$ e

/ e3 r2 Q& y8 B
; u! Z  @/ t$ L8 C' M( q5 K" g0 j理论上PCI bus支持256条总线,每条总线支持32device,每个device又支持8function,所以我们组合出上面所有的可能就可以遍历出所有的PCI 设备了。可是实际上PC上面PCI 总线通常只有1条,最多也不会超过四条所以我们只扫4条总线就可以了,不用做太多的无用功。有了前面的准备,我们就来实现一个类似RU中的PCI scan吧,下图3就是我写的pciscan运行的状况了:0 V2 H' b  F; @, {+ L0 `* @( w

/ |" N  a3 p' B& m       pci3.JPG                                        . \3 i  C# X, b" s4 O3 w
  w4 s  }  r' T' [% E: n
3
0 M2 l) F: i7 t, a1 o( {8 S4 W
在该界面下按下esc就会退出该程序;移动↑↓键就可以选中device,然后敲enter就会看到该deviceConfiguration space 如下图4所示5 |4 y3 h8 z8 u/ w  q! \5 k5 _7 a+ u
pci4.JPG
% A1 v- B/ m, O2 t& A/ g8 U& C7 L. ^( a" ]+ G

7 H7 D* y3 s% ?( y1 P 4

0 p$ F2 f' q& V# i7 k  e* n当前界面下如果想返回到上一个界面只需要按下F6就会回到图3的界面了。
. ^& c7 b  u/ Z5 y# ?6 z# K, h$ V1 m+ B  v& p2 S. I
2. Call PCI BIOS int1A同样也可以获取PCI device的信息。其中AH=B1hAL=function id所有的function id如下所示:
8 \9 I* c4 j4 b/ f8 n01h: INSTALLATION CHECK9 f: i) a# k: K9 ^% g6 g
02h: FIND PCI DEVICE) r! k3 U' _. I
03h: FIND PCI CLASS CODE4 s0 C5 N" y9 o+ C( j/ Y
06h: PCI BUS-SPECIFIC OPERATIONS
' F) \6 f+ e$ C* [0 a08h: READ CONFIGURATION BYTE' N6 ]) I4 H1 }+ z0 }
09h: READ CONFIGURATION WORD/ P" P/ b6 t5 w0 l; q) L% c( D
0Ah: READ CONFIGURATION DWORD+ \; Z( o7 I& K; m- o
0Bh: WRITE CONFIGURATION BYTE
  Y4 v+ y! Z' K1 @' ]0Ch: WRITE CONFIGURATION WORD
% E: V/ a3 A% b, N2 p& H  `' A0Dh: WRITE CONFIGURATION DWORD
# T2 ~8 m. U# P- s& G+ O' v" p0Eh: GET IRQ ROUTING INFORMATION
- G4 Z8 I! b6 l6 o, m9 E: f0Fh: SET PCI IRQ3 z9 s2 _, P" i
81h: INSTALLATION CHECK (32-bit)
$ s; p2 S& |  \# B1 ~. y3 n' f4 o82h: FIND PCI DEVICE (32-bit); y5 Q2 N* b% X& @. Z1 B/ R
83h: FIND PCI CLASS CODE (32-bit)# \% S0 I  d5 S; L* F! I  J/ Z$ T# ?
86h: PCI BUS-SPECIFIC OPERATIONS (32-bit)5 }0 p- _" h: V! ], u" l
88h: READ CONFIGURATION BYTE (32-bit)
7 y5 e/ R: z# G( |7 v0 Y89h: READ CONFIGURATION WORD (32-bit)
, ~6 t) C2 P) F/ Z. l. E8Ah: READ CONFIGURATION DWORD (32-bit)  Q2 j$ q6 K4 a% ?7 t4 s
8Bh: WRITE CONFIGURATION BYTE (32-bit)
, p3 d* V& n* Y: B2 C8Ch: WRITE CONFIGURATION WORD (32-bit)+ @8 j3 N& u% S+ X
8Dh: WRITE CONFIGURATION DWORD (32-bit)* H7 I  [3 h# ?) r8 A4 w: a. q( s
8Eh: GET IRQ ROUTING INFORMATION (32-bit): p3 ^3 Z. f* J4 `- b! u& ^4 I
8Fh: SET PCI IRQ (32-bit)
# h9 c& q  J8 }) |我们使用function id 09h就可以从configuration space 中读取出一个字,这样的操作明显简单的多了,只需call 一次int1a中断即可。下述c代码演示了读取Vendor id的过程,如需读取其它部分只要算出具体config-address即可。
, I/ j/ E+ v- T
3 n: y+ F0 ~  w! Z; S#include <stdio.h>. U! a; I% V; q; r2 K, e
#include <conio.h>
/ }; J0 D7 ~3 v( H7 a: m#include <dos.h>3 `# j( o. K& Y8 d) p
* V0 D5 `# E" t! E8 u, @7 O
int main(int argc,char** argv)
  M. J4 T& U. D3 e) i) `" s{
+ U) e0 x. J- u; _7 g5 {0 \" I' W/ k# a$ |+ W
     union REGS reg;
  g0 ^$ U) z! E* q" y& C1 v( _( M1 K* k; ^0 E5 L: E" W6 l
argc = argc;

$ f$ H2 Q3 ~; v) s, o7 ^
, y$ m1 D3 w( t& R) c  D, X' y0 Fargv = argv;

9 `0 s9 e, k' i, z2 w2 Y* }/ V5 x( p' I% O" d3 z, z4 W
reg.x.ax = 0xB109;
% V) A2 A6 P5 v  k+ e3 p: \- e  p$ K) V

! ~; S& i" Q, S6 t8 Freg.x.bx = 0x80000000;

: W2 o( \- E$ [' v. ^! E* l
3 l2 B  F( p3 M. {( ]. \
+ m. g, ~* F% C, G, rreg.x.di = 0;4 _: c$ q. W, S2 Y% ]
9 s6 n9 ~+ F( w0 L
$ ]+ w- J& Y& z6 I! A& u" U
int86(0x1A, ®, ®);
; K! @! T0 o9 o' [  l. s0 `

  L+ A3 O1 @. J9 Q0 [+ X: o     if(reg.x.cx != 0xffff)- ?' S, L% k. X+ b! r0 Q' a

& Y7 V$ f0 H# A7 k. ^- k! d! Y{

* ~6 F6 b. \; n/ _: S5 ~$ o3 o9 n/ j
" a8 q$ \- P* U. T( zprintf(
"Vendor : %4.4X\n", reg.x.cx);
9 v5 u% e" y% G! s. [) i) ^
3 b. |( N( @- S5 V4 c# @) z
}
3 i( A2 q8 q- Z, y

1 ?( Q: A$ H3 O1 S$ h     return 0;
# I* k) l9 Y4 C, y" l}7 z( B9 E! t. o$ Z3 g$ |2 E/ _

7 E  X; I5 ]# N1 e! ?0 u程序运行结果如下图5所示:7 a! Y  s6 ?# @" k8 F* ]4 `7 L- a
/ g( T" l7 t( v" u  y9 C
pci5.JPG , p  T: G2 ], N+ U: X
' j% V# p4 `. N3 k  B4 Z. X9 L
5
# x; q6 }: `, H4 L

) K/ T3 P) i7 F3 f. d2 b5 ]  D最后依旧是开放完整的source code和可执行文件供有兴趣的朋友下载/ m- O9 k* y6 F8 l( [( k

: l/ Y& x: B' ~2 ~2 ~
) I6 w& F1 V  e
Enjoy it!
1 @. ?9 L, z& U  z2 F) [2 h2 \( A
9 V. }9 B- u4 X4 B+ W
, i1 H2 e5 P( i, ~) jThat’s all!
9 `7 r+ v" q9 F8 r0 ?- S, h. q. {  E3 |* {& m+ a* T
Peter 9 w3 X2 e6 n( \1 d9 W
1 t& G9 w# z9 J7 \5 N  ~  K5 v
[ 本帖最后由 peterhu 于 2009-7-6 16:55 编辑 ]

PCISCAN.rar

4.69 KB, 下载次数: 1409

回复

使用道具 举报

发表于 2009-7-7 11:28:28 | 显示全部楼层
厉害!!!!!!!!!!!!~~~~~~~~~~
回复

使用道具 举报

发表于 2009-7-7 13:35:14 | 显示全部楼层
Peter Open Source 的观念很强啊,想当初小弟刚开始接触BIOS的时候,要是碰上你这样的大虾,那该多好啊...
7 G* k' O- j. ~4 c0 rUI 就不用画那么辛苦了
回复

使用道具 举报

发表于 2009-7-7 13:40:56 | 显示全部楼层
同感,同感!!
回复

使用道具 举报

发表于 2009-7-7 14:47:21 | 显示全部楼层
支持LZ     !
回复

使用道具 举报

发表于 2009-7-7 15:50:58 | 显示全部楼层
预祝Peter转业成功!
回复

使用道具 举报

 楼主| 发表于 2009-7-9 10:17:02 | 显示全部楼层

戏说BIOS之Clock Generator

戏说BIOSClock Generator

, E& h3 E6 [4 z/ U  y; \  `5 l* o# i

- a) c. c5 r5 c, l1 R1. Introduction+ }- [& x5 w# M% w( r

: O" k4 A9 q* o1 V: }& |: uClock Generator是主板上面一颗极为重要的IC,说它极为重要一点都不为过,因为Clock generator负责提供主板上的clock, 一旦Clock Generator除了问题,板子基本上就完蛋了。Clock generator供给的clock部件有CPU clockPCI clockAGP clockPCIE clockSATA clockUSB clock等。

7 e) C( o+ a$ _2 `- `% S( S3 r. J" i

8 Z- {. \1 u$ i9 w4 ~2. How to work?
- _0 A$ ~: m: A1 @
, M7 l$ k" g* I) aClock generator 是一颗IC,它有一颗外接晶振,内部会有锁相环放大调整电路,可以将外接的晶振产生的clock放大调整然后再分频输出到各个外围器件和总线,提供器件和总线工作所需的clockClock generator的工作原理如下图1所示:

  S1 {! N0 `3 D8 b* F

$ o4 c5 D2 ~' d3 u% R cg1.JPG , u% l' J' \# Q$ |/ s5 y  q6 h8 K
Clock generator通常是一个smbus device,接在SBsmbus controller所以通过SBsmbus controller,使用标准的smbus protocol就可以存取Clock generator上的configure data从而达到配置各个外围器件Clock的目的。鉴于clock generator的重要性,所以BIOS在非常早的阶段就会配置它(boot block阶段),让CPUmemory等的工作有一个稳定的clock。下面我就以VIA平台为例演示Clock generator读取过程:
# }1 W5 Y/ h  [6 S% F# }/ |6 x% I% ~( I2 s  v
  • 首先要通过PCI配置空间找到SB smbus controllerbase address
  • 查看Clock generator smbus slave addressICS9UM700 slave address42h
  • 透过SB smbus controller下达slave address & protocol完成clock generator数据的读写。

* q6 B( a7 q8 A  U& U5 Y, z下述code演示了获得smbus contoller base address的过程:' t6 h: k' J7 ?2 q* E+ d$ K
;----------------------------------------------------------------------------9 k- }8 g' f8 Y& S1 X
;get smbus base address) l+ y2 ^  ^. G9 l# d: }$ e3 l
;used registers:eax,edx
. V: t* \& ^& W/ C& D# T;called with:NULL
1 c5 s+ o% c) F  y;-----------------------------------------------------------------------------9 d! k' `: _6 ]% ^
get_smbus_bar proc near
. E5 {& W( b% A: [$ ~( _
. ~$ k& {3 y+ D8 Q( ppush edx
$ w1 A) x3 `% m' _3 o* ^9 Z# I+ a, Z$ \

+ i4 b8 E0 j/ L, s$ Opush eax

! d0 S2 r- ?  E: k' Y- i+ |$ |. Z0 n/ W
mov dx,PCI_CFG_ADD
; _2 G, H7 j% y

" `8 T9 Y. d7 ?mov eax,PCI_SMBUS_ADD
) o* s. K& S' A0 q- ]! T# u9 C: M

9 j; l# H+ d  h: i0 h3 t( k" ?6 Pout dx,eax
! B0 l7 X# Y# W. X9 S9 o( W2 X
4 v3 ]2 H# e3 E! e/ B4 a
mov dx,PCI_CFG_DAT
, m( e0 Q9 f- _% m- M0 b9 x/ R
7 z7 u. O5 Q- b" m6 e
in eax,dx

6 Z+ J0 Q3 ?0 O0 b# `
- v$ [0 p. D+ I% p" q) Nand eax,0FFFEh

0 f9 v! H. [  @+ H; ~! o5 T% N) i" F
( j; A. n& Q3 ]+ g/ dmov SMBUS_REG_BAR,ax  z1 Q: l* M) |# c' f# K+ }' }  W

, t3 j" X+ ?9 o9 W* [! h8 U6 Rpop eax

, w' M$ ?9 H* I9 Q/ w0 E
  R  N$ R3 x6 R5 [6 Vpop edx
) }( A+ {7 p5 P% J

# c0 G' c8 ^" R" {. ]ret

% f$ m+ p( F) M& h4 c" a* C  tget_smbus_bar endp1 e" r% i5 P# u8 h

, S3 j. `& b4 U. a7 r: _& U( q下面的code演示使用read block protocol读取clock generator configure
  I, f0 G* J7 {: ]8 |( T; u- r& ~data的过程:( k( J/ J1 x" }% z2 O
;----------------------------------------------------------------------------
" z& Q6 H7 \1 T;read via clock gen data by read block protocol7 {8 J: X5 B, b
;called with:NULL% z7 i6 P; Q% ^. F& O  z5 I/ w
;used registers: ax,dx,bx,cx
5 O  d, y* O; C1 [, [: o* N2 h

  k& S: G' t, i;-----------------------------------------------------------------------------  g; z3 a0 \4 u9 G' R& Q
read_via_smbus_block proc near
& b; d6 _# r: D+ w( y8 l
, C7 s1 [$ N# H" L7 apush dx
- U) m7 v8 {8 @* y! @+ l! O2 S

7 ^/ K8 j4 W+ N4 _0 t7 jpush cx

% T# H9 J1 b3 ]) e2 M
' T! {8 P6 D8 Mpush bx
& f# d" g: ~3 G  N+ p+ Y
' a, L1 I) |% g
push ax
; M+ `! H/ h1 {9 G' K
: Q& N6 k# O$ D3 D# |3 J
. P$ W+ n/ Q, C: @$ H+ h0 }8 ]
call get_smbus_bar
) B" J  ?% ]! o6 h& q6 n

. R4 z0 Q, \9 G6 [! W;reset host status registers
1 F+ d* L9 I0 `- r: Z( Q: X  e

( g7 s& m, ?6 F/ n$ k, C4 V( Dmov dx,SMBUS_REG_BAR
1 l8 D; k  [8 U$ Q% c6 w

3 P1 z' a6 M; D0 T0 J# S5 aor dl,SMBUS_HSTS_REG;(00h)
' j# Y  k4 O% B! B: ~

9 E5 J5 H  b) a$ w6 M2 ]mov al,05eh

' v; K$ o/ r0 h& j  @, q* [) z% q2 B$ [) b& X0 s
out dx,al
( b2 a7 s, a1 W9 ~, _! X
5 C) v7 i: t8 D; J& F  |

3 v/ L- v0 e  w5 @8 s;set smbus slave address

- c8 I1 e- }0 c3 y. r2 S( N$ F% ]8 l( [, d6 F
mov dx,SMBUS_REG_BAR
, p* u& \+ L# t; G  C8 l2 x
+ E9 `) k# m* C, {: t
or dl,SMBUS_HADD_REG
+ R" c. N; B! F- ^( e7 u
" S2 j) {# x7 u& t6 a) g
mov al,SLAVE_ADDRESS

2 s! B+ L! x; M0 }6 L1 l0 Q9 a* x. p
or al,01h
  a/ r) d8 S5 Q9 ?/ L. u
9 r. ^6 E# @6 Z0 M2 ?
out dx,al

+ B: b) ~) ?- r9 \7 M$ w3 _1 G# x+ q; X  _2 F
call io_delay
" {% H8 ?6 k2 W

& [- Q/ e7 T' f; z7 L* a# E
- M9 m/ m: f% ~& P;clear smbus status
# l) P+ h" P8 C$ }" \2 m2 L

  u' @0 c2 [$ S- y3 f; Z1 b6 o) x  M0 qmov dx,SMBUS_REG_BAR

& g$ K; v1 e9 J5 F% K: w4 Z% W2 w
or dl,SMBUS_HSTS_REG;(00h)

" V& m; d. P* R* Y, o: R$ D* u) L1 W$ j- f" g' l8 e
mov al,05eh
& X. Y* b( o/ F/ H
& O. S& S4 i5 t( z" g8 t
out dx,al
. J8 y1 |" J* _. P' B* \4 B

) f: r# n/ _- mcall io_delay
9 J  q9 \, q" G
4 E5 P( v" i: x$ e" u& e! C

  e: O' Q/ o9 {+ J;clear smbus command byte
' P/ U3 `+ C' }# H# ~

6 O4 h) d3 s) t( a6 S3 Smov dx,SMBUS_REG_BAR
0 ]& o( U+ N8 y* b

2 f! y* O' W$ lor dl,SMBUS_HCMD_REG;(03h)

8 K) F- l8 i, f2 _
. v9 p% E- F# j5 m  O% Y8 ]3 Q) Jmov al,00h
  C. f4 C5 D7 `3 c  F

) L7 J! n! R" t% ^2 u' L+ Y* @out dx,al

+ H/ A) ~+ w5 `9 x0 ]- R( l1 m( z& ^
1 Y2 V8 Y% l8 ?1 q5 G8 G1 L
$ O& p7 o+ ]3 r* ^3 G;block read protocol
! b% N4 Y+ _3 L# V  M0 G

7 h+ _  |* D" D" P. Gmov dx,SMBUS_REG_BAR

- I1 _& {: a, Y6 s- I. {8 e
& m3 Q" D  P. }: For dl,SMBUS_HCTL_REG;(02h)

  F" m8 v2 L1 b7 a5 X/ I
2 P- I, {( L3 ymov al,54h
$ Q6 W# ^, Z; u+ P$ }) J

$ ?3 a7 s( r  G( T( }' bout dx,al

& O8 s& U+ Q# y! k' b/ C
9 L$ v$ l% H0 N. Z  z. L, j( Icall io_delay
. G$ y3 s% K8 l/ r! B
: C4 y; J, K" |! _  p

# Y3 N5 v7 i1 k/ ^;wait for smbus finished
, I6 q+ J9 }8 M2 f

0 M  [: Q  U! G; l9 ^* W# Gmov dx,SMBUS_REG_BAR

! d4 T$ h) F* a- m
' D, G3 ^' G. S% [. |) }or dl,SMBUS_HSTS_REG;(00h)
6 l1 ?% J! {1 f/ M$ U

( B! e& ]# T  g" K  x# i1 ]rvsb_wait_smbus_fi:
0 Y. v6 E: Z) ^
2 X# C, s3 |( ]2 V: iin al, dx

" P4 y+ {; I7 z! O" ^0 s) V  L9 k9 q5 B
call io_delay

: ~9 y3 v2 ~0 Q2 x' `6 V' V8 G
( P7 A. K* E0 B% @# z& qtest al, 01h

! t" A" N0 ?- U* a- }0 Z1 H: N1 R  P  j
" S5 b) t0 H4 X! P7 y( U% }1 kjnz rvsb_wait_smbus_fi
4 `" b* U( [" f* w6 Z7 I* A5 W
1 g3 S5 C  @* L5 k% k
# o& Z, J4 D+ p0 p; @
;read data count

' M8 Y$ e; ]8 t$ O' d
& Q! h6 D8 D3 V/ cmov dx,SMBUS_REG_BAR
5 @2 T& q/ G0 g8 K' i$ R* W

2 ^( J2 P& Y+ i$ ^! N! V+ |; Yor dl,SMBUS_HDA0_REG
+ C3 F) g; @7 Z
- d. o) r) V% z
in al,dx

9 }1 K% r5 h$ m
: U9 W& `" p( C;read data from smbus block data
) j, ]) l9 q6 }! Q3 [

* R. M, S, i1 f3 J" O3 O6 @mov cl,14h
9 }6 y1 |! O, p- R" z1 f; v
! b% P( b$ E1 l3 O* ^$ ^* E
mov bx,offset REGSTR
( q' c% s' B& I% M; N% f
rvsb_read_data:2 u0 D5 r: t, [/ q% J+ n9 p
+ ~( D* M5 p$ r) `
mov dx,SMBUS_REG_BAR
; h$ w" d' q# S; O1 [: o; k

9 }: @  e- H" U# w$ [0 oor dl,SMBUS_BLKDA_REG
' w2 f/ ~1 K7 r( i, I
% M/ n: u7 `* U! \8 ~
in al,dx
! o4 B7 b0 B( b& R; F" K& Q

2 d1 B! M- r9 f5 I2 Q5 n* Ccall hex2asc
/ m+ T/ `6 C- S6 c& e
5 [6 V/ C0 [  A7 T
dec cl

2 K% Y" b2 G. W$ e  E/ P4 ~% K. E
( ~! ]4 w! s# U9 d3 H( Cinc bx
3 k; C; u) |" k* S
6 h( ]) C2 r6 j# i9 \" a; y$ O% C
inc bx8 N* O# h0 C) H5 d, e

  A& f6 ]" J1 T& h) M  Acmp cl,01h
1 }) S) F' a$ ?4 s% ?" l/ d7 V. {& y2 |: @' \7 @, k# Q: f
jae rvsb_read_data
8 r( a# u; h$ F# U7 t2 ~* g* }& S! _9 z3 j# m: V$ B4 l* Y6 r3 s8 j
pop ax7 g2 X! f$ F5 A4 H$ o
1 b; E4 H$ c5 L/ R1 r* R
pop bx  Z5 `- o. y9 b7 f1 ]

7 z6 O- W) x0 `4 k. t2 T+ Zpop cx. j3 H" E7 P3 s1 r
  Z% k3 n$ g% d( d: E. O
pop dx
8 a0 d$ E7 Y. l& ]. h" d1 j# Z7 V5 L6 d
ret
: j5 H( `0 s; f1 y$ \read_via_smbus_block endp1 e& p0 Y/ l" s- l, v

' I6 P- n  y* s下图2演示ClockGen.exe运行时的状况:
$ ~: l) B2 ^" Q6 ?6 n  O; b# d3 P
7 e% c6 c$ d6 }/ C' H$ Z
cg2.JPG + d* n. F1 U) p% v
              图2

) R* z$ y' i% h" \) SClockGen.asm只演示了VIA platforma + ICS9UM700dump过程,至于其它的平台,有兴趣的朋友可以如法炮制。那么这只tool可不可以做成通用的呢?当然可以,只要从PCI configure space读出Vendor id识别出平台然后再根据具体的平台spec去获取smbus controller bar(可能要多看几份specJ)然后就可以操作smbus了,clock generator slave address可以让用户输入(我看到的几个都是42h,但是也会有特例)。我比较懒,有兴趣的朋友可以试着完善它。最后依旧是开放完整的source code和可执行文件供有兴趣的朋友下载。
* O  L# P& ^( Y+ M4 s( J: Y

" J. m7 H. p7 G0 S4 i; m& [
" a2 I! C: b5 G5 z3 u/ [; D
Enjoy it
; X, W5 G2 {8 u$ d* u" R" p
  l8 m) J! g. Z9 W- [5 h; P+ X/ H4 B, [
That’s all!
8 m0 z& [0 H. t: g9 h# }) d' c9 h  R3 H; A: T: R( R5 v- L3 [
Peter / z6 W8 h4 q. G5 g1 O8 S
/ @; x# w6 Z& a% s9 F5 c
[ 本帖最后由 peterhu 于 2009-7-9 10:26 编辑 ]

ClockGen.rar

4.1 KB, 下载次数: 1388

回复

使用道具 举报

发表于 2009-7-10 15:03:12 | 显示全部楼层
向Peter致敬!!!!!
回复

使用道具 举报

发表于 2009-7-10 19:36:38 | 显示全部楼层
Peter兄,这怎么能叫不务正业呀,我也是BIOS和EC都玩的。
回复

使用道具 举报

 楼主| 发表于 2009-7-10 21:21:19 | 显示全部楼层
Alexander 你功力深厚啊!; j7 n% r: B! D% y: i* k
呵呵...向您学习.
! g7 A0 G' H$ V- z7 v! M. w! O. ?0 L. |7 u# E
[ 本帖最后由 peterhu 于 2009-7-10 21:22 编辑 ]
回复

使用道具 举报

发表于 2009-7-13 14:40:45 | 显示全部楼层
好强大的帖子 我正处在入门阶段 能看到这么细致深入的教程感觉真是很激动 拜读中
回复

使用道具 举报

发表于 2009-7-16 13:14:42 | 显示全部楼层
peter,可嘉可贺!
回复

使用道具 举报

发表于 2009-7-20 17:08:06 | 显示全部楼层
俺也搞了个类似RU的东东,献丑了。

Hardware Editor

Hardware Editor

HE.zip

32.81 KB, 下载次数: 1296

Hardware Editor

回复

使用道具 举报

发表于 2009-7-31 23:17:14 | 显示全部楼层
Faintsnow好样的~2 O! r* Z% I0 P/ u' k
这个Tool实在是太棒了, 很好用哦~  h! L: D. Z/ t/ M. D  L
我顶~~~~~~~
回复

使用道具 举报

发表于 2009-9-4 23:24:56 | 显示全部楼层
顶楼主。
: X* Q2 d8 w' m7 S8 W" }, M拜读啦,O(∩_∩)O~
回复

使用道具 举报

发表于 2009-9-11 00:12:07 | 显示全部楼层
还真没有几个能够“戏说”bios的啊。 你算是个高手了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入计匠网

本版积分规则

Archiver|手机版|小黑屋|计匠网

GMT+8, 2026-6-11 20:39 , Processed in 0.270346 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表