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

戏说BIOS

[复制链接]
发表于 2009-7-6 16:05:24 | 显示全部楼层 |阅读模式
戏说BIOS之Hello BIOS3 O! X+ Q, }, D# Y4 U0 ~, `

/ E4 X# Y( B. t. Y9 ^: ?& K, |) ~) g& L# d) p
“我所知道的EC”系列基本结束了,现在我终于可以有空玩一玩BIOS了。可是需要特别强调的是我是一名EC而不是BIOS,所以我看BIOS的视角可能会不够专业,也不够正统,这也是为什么我将这个系列取名为”戏说BIOS”的原因。可能有些朋友会觉得我不务正业,身为EC却去玩什么BIOS(呵呵…我本来就是不务正业J),我觉得PC本身是一个非常复杂的系统,从经验来看很多问题都不是孤立的,通常会牵扯到很多的环节,因此如果将视野局限于自己的一亩三分地则很有可能见树不见林,看不清问题的本质。所以我觉得全面细致的理解系统的各个环节非常有必要;而且我的技术目标也是希望通过n年的努力能够贯通PC系统从EC->BIOS->OS->DRIVER->APP的整个链条,把握系统的运作的脉络。关于这个“戏说BIOS”系列,我打算先练习一些BIOS新人学习作业,如:cmos dump,kbc access,pci scan,smbiosdump等等;然后在对我感兴趣的一些BIOS的领域做一些study。现在让我向BIOS世界打个招呼吧: “Hello BIOS,I am coming!”。
6 L, K# Q2 x+ M- n
data segment
, K1 Y% \4 [+ R, J) ~' z: R2 Y  W1 |1 o
HelloBIOS db 'Hello BIOS,I am coming!$'

  k1 A8 I+ A/ D% W. \
' \6 E( U6 W# F3 H8 l/ [% E  udata ends, I8 N$ |; B" F' [. Y' K
9 y. T% q6 c% l: d& R& k: J0 J
code segment
& [- Z2 `+ O, i9 V# ~3 v, Z1 J  D% ^& D3 Y2 Y: \! y% i
assume cs:code,ds:data
' R# p* K; H% @6 X* b" h& n( {; `

: l/ n# ^: s; N8 |start:
4 _! {; s1 q3 n# t; X2 j

0 R- S  m, R5 P  v- f: X# |mov ax,data

& h2 v; a6 B1 p1 _: }1 n
2 H' |3 ]$ ]& i: h( [6 X+ e( X1 |5 r/ }mov ds,ax

& [4 e+ _+ J( U& ?
2 Y* ?' I( [, F9 jmov dx,offset HelloBIOS

/ J  `9 u# {2 {# F. R. I: J' {* B! Z' E9 v
mov ah,9
" H2 P+ P3 X1 b

% E$ E$ O, ]) G( O# Vint 21h
* N* S! d1 t( P  O( `* K3 k; k
  E, W5 Z. k$ @, [( a$ J
mov ax,4c00h! \4 g' H- P( Q6 z
) B1 o: G4 F) f
int 21h

5 X8 j; W6 c& M/ l% }  Z
: L$ u* L. L  J+ Ncode ends5 J5 h3 i: G) M; s

! `/ k* V6 W+ ]/ J7 h9 yend start- D7 n" M2 O0 ~

; R! w5 L# U6 L: vThat’s all!) M7 V( D4 o% y0 N2 t0 q
Peter - b5 v+ J* N- J$ m1 K$ e& ]+ V1 t4 s/ y

0 [2 D) ^: i/ b8 D[ 本帖最后由 peterhu 于 2009-7-8 09:13 编辑 ]
 楼主| 发表于 2009-7-6 16:07:54 | 显示全部楼层
戏说BIOS之CMOS

) W: i- T" e" N% Y
& i* k0 W" t. z5 @
1. Introduction0 R; A- j! R8 m5 N& E, g$ G

- w0 J8 \" N9 F+ H3 T* v1 iCMOS全称为complementary metal oxide semiconductor, 翻译成中文就是互补金属氧化物半导体,它是由一颗小的纽扣电池供电的128/256 bytesram(现在的chipset通常提供256 bytes或者更大的空间)。它主要用于存放RTC以及一些oem的系统配置信息,所以除了RTC等部分其它的很多信息都是undocumented& non-standard。RTC 标准的(documented&standard) ram bank如下表 1 所示:' q2 c6 ^$ O: P+ \* U* d
0 r; r6 a! A9 O8 C
Index
; q: c4 T3 y$ |8 d4 n% a1 T; P
Name

; Y) d! L$ z8 z/ z) V( S7 J! D
00h
7 D" C3 H) B) f$ Y& I
Seconds
% D/ `7 M8 T4 F, ~5 `) B
01h
$ r! M/ f& w; d9 e6 I) j
Seconds Alarm
+ K9 R, t- G! j+ v
02h
" `  a" q/ @& z, Q
Minutes
4 B5 _7 \# B" e* `' Y! d
03h: B5 G$ n2 [) o- H$ q
Minutes Alarm
' {0 [! x" ^& b" p- N3 h9 M$ W6 n
04h
) P9 i* t. @( G6 S
Hours
1 C( E" V! N1 T+ J; a. \5 S
05h
1 B8 o& Y, a9 n3 v
Hours Alarm
# q8 r! V8 B" M+ }  g7 L  @
06h- s) n* ~( g" Z4 j; z
Day of Week
, q, V# Q5 t' `
07h7 |# m8 Z& a7 o2 ]) p
Day of Month
+ r: [. i5 k- E# C  ~0 I5 t, P5 l( G
08h
* |0 O. {, p/ e
Month* {( j3 Z, {# F5 l
09h
0 m# k# F/ `' p7 S) {0 b. |
Year" l6 e3 `0 _+ A& c4 C
0Ah
  o6 B9 J7 J1 p& o9 H7 p, r2 _
Register A
3 {7 d$ h8 m4 N
0Bh
- o0 H4 l' Q' \6 |. M* |  Q1 G
Register B# |  L/ l! X4 R$ j! F; L
0Ch- p- ]' T0 Z  ]! d! q$ N# }1 b
Register C
( R) n  f. y9 @6 U5 t1 M3 n7 Y7 G$ J; u) g
0Dh5 m( |6 e+ S5 d3 s( T8 G3 O- `0 m
Register D
, B) D6 ?$ P! O
0Eh-7Fh
4 `' C" G% y, _1 U# X
114 Bytes of User RAM) A0 J* E2 {3 M! m& [: y: q( F9 o
                 表 1; y1 ~) U6 r* E) G" A
3 r: S& i: I# K) F
2. Access Cmos
/ p4 t0 F% e9 n' p: ^5 R/ v$ E9 }6 s* R/ @  t! s1 {
3 \+ P* x) d6 H. H5 K+ n
访问cmos通常是透过70h,71h这两个IO port实现的,有些chipset支援256 bytes的cmos ram,访问128bytes以后的空间需要开启chipset的始能register,有些chipset使用72h,73h访问扩展的空间如intel chipset,有些仍然使用70h,71h如sis chipset,因为这部分是非标准的,故后面的练习程序就不去读写这部分ram space。读写cmos的过程非常简单,读特定的index的内容只需要将index送给70h,然后就可以从71h读出对应的数据,具体过程如下述code所示:

) B8 Z. q  b- s' q0 C1 `2 ^: ~;----------------------------------------------------------------------------
7 J  |( W3 `: d: F* Q6 H
2 T, I& \* ]4 ?
;read_cmos( @/ ?+ n, G3 b  j- D2 |: D
;read the contents of a specific CMOS register# O5 C8 t4 m5 M; ~) e5 e
;call with, h5 s% k$ M$ b& c
:al = CMOS address to read
6 I* _9 ~  g* L6 U/ w' o" t( R;returns
3 G+ Y  @, T7 f! D:ah = Contents of register  e( l' ?1 U# |/ |
;used registers: ax, U* A! x8 i' J4 v
;-----------------------------------------------------------------------------
) i8 T; p5 _6 x/ kread_cmos proc near% k& N9 H  ~1 F- R9 s9 v
: D9 |" H9 d& `: ?% ?. B

  }" Q6 z& v: o) `cli

8 ]- R  G5 I2 @1 O8 |1 I2 s& Z) T& t! I1 t( C, z9 f3 b! {
or al,80h;disable NMI
/ Z1 f0 e1 L# H7 P' Z

8 Y8 I8 J1 d) J* M+ K) tout 70h, al
6 a% r* Z$ J- T7 g# K8 D1 `
4 S+ X; J& Q; Q
call io_delay

) a' s+ Q$ x- H& F  r  L
! ?3 Y% ]9 k' J9 e6 Z' E! gin al, 71h
6 I2 B3 L; d+ c+ E/ S5 [
  W; B7 J7 R, V9 M% K
call io_delay

4 Y7 e& U) o  o5 Y% p
- z1 j8 _4 M1 Y& imov ah, al
, [7 [: C! R% f& p1 o" N0 E
0 U2 M5 b& P6 c
xor al,al
8 H6 N; t: |9 X3 m% a
+ G! ^4 |1 {% d$ A; [7 g# o
out 70h,al ;enableNMI
+ E4 q/ `/ f' b% q1 s& S7 d
  R3 F% }+ E# P& R; J
sti
# |9 |- O; q2 L# \; w( v6 b

1 U6 L- }3 f4 L8 @5 N& x# rret

+ x- L. c8 r3 L/ x' G; e2 p" M0 z5 g$ s  N- K5 {
read_cmos endp8 k  L9 B- w+ S) A, g4 K
写操作和读类似,只是要将待写入的数据送给71h即可代码如下所示:& f4 D4 z* f- f5 b. K2 j: B
;----------------------------------------------------------------------------
5 C+ |2 q5 s5 I9 ~- A6 s, \
/ t% ?. K' F* t7 t: i# Q' v- |! Y) z6 M
;write_cmos
6 P+ a; f3 E5 }, g3 m) @. r. r;write the contents of a specific CMOS register
9 F4 F5 X) U0 j1 T;call with) ~  {0 p* i2 r& c
:al = CMOS address to write1 Z6 O; `9 H5 a8 \8 f+ N2 [3 ?3 x
;ah = Contents of register' Z, M, J1 l# \) J1 p3 A8 d* n/ G
;returns:NULL
# k# B+ C; \+ [3 ^2 y' m, `;used registers: ax
- e3 O6 m1 X9 i! j5 C6 \;-----------------------------------------------------------------------------, V' l2 n  @6 P8 m; I$ P8 d' B& K6 D
write_cmos proc near! _: h5 M6 m4 r: C4 n) L* z

# k' _8 I0 A% [/ gcli

- |- P6 O  u1 G1 }6 V7 S: g# [( s
or al,80h;disable NMI
0 P+ R& t! T. m/ B  V
! o; C2 p' k" M. _6 h
out 70h,al
4 B3 g$ y' g3 s& r
( T8 Z& d1 b# J9 Y! U
call io_delay

/ O3 e3 P0 p- S- z% b& A. {  _- S9 q- q* Y$ [, t6 @
mov al,ah
! J9 T7 M- U4 ~: a

1 K: r' z- ~  m( sout 71h,al
; N) M: v. Q# H2 H
+ q# C3 U6 Y. U5 U
call io_delay

/ r  s( y) }# m$ R1 c8 @
$ u8 H: W4 H. A# h& {xor al,al
7 q9 ?* k! d4 v$ u+ T7 _
  T) }  [. P1 g
out 70h,al ;enableNMI

4 M8 N# W4 Q; O6 y/ w* v: _& m, B- o6 {% u
sti
3 E$ F3 O) h+ m# G! }: `0 g! K
, B& z/ m+ a, O. f  Y
ret

2 n1 b5 q& q9 U2 ^# k0 I1 d0 f$ k
1 z8 v: m$ y2 _write_cmos endp# h- @1 r8 a- o7 I) V6 ^- [

1 q) z* G4 [* d5 N2 f另外有些细节需要注意的是:a.读写过程中都需要关掉中断以防止,中断处理程序访问CMOS以及RTC更新过程中可能会导致并发访问。b.NMI(non-maskable interrupt)是一种中断向量为2的中断,但是与常规中断不同的是它不能通过mask register屏蔽掉而且sti,cli指令也对它无效;NMI通常用于一些无法恢复的硬件错误,访问CMOS时也可能产生NMI,所以需要关掉。NMI可以通过70h bit7做开关。c.状态寄存器A bit7记录了RTC是否正在更新,如果正在更新则等到更新结束再去读RTC(我写的cmosdump因为偷懒没有检查这一个bitJ)。$ Q6 Q1 J& L% M# i

$ |: B$ B' P0 o2 D- Z! h3. Msg Based Event Driven% j& I' d- B3 c
+ n5 y0 _# {& D  H) A5 W

' ^. N6 h) Y5 {3 S知道了以上的知识,我就有能力写一个类似RU中dump cmos的工具了下图1就是我写的cmosdump:
$ o! `. S+ ~4 {  Q7 e9 L2 }: y& S+ |
/ Z- B0 i9 f. M) K
cmos1.GIF
. F) Z0 W+ {4 G7 ^我觉得访问cmos本身并不困难,画个UI倒是挺费劲的,一个劲call vbios
! ^- ~: I5 R+ m$ B% @& f5 d另外在完成这支tool的过程中我更深刻的体会到知识是相通的了,windows编程的经验在这里发挥了优势,为了能够动态更新,实时修改我就借鉴了windows下的“基于消息,事件驱动”的机制Mainloop->GetMsg->TranslateMsg->DispatchMsg一路下来好不快活!这部分的代码如下所示:6 y* Y; k' Q1 V, \
% {" l5 ^) h' s" T. t( G
9 T  E# e$ Z, b2 q, b- f; \+ z
mainloop:  I9 X- ?! b6 H. r1 g

( q7 v$ U2 ?6 v9 v" s) y3 F1 b* Ecall show_index
% o7 e$ b8 c" Z; J" T& S

( H4 w. r4 o- l( B- T& P: v7 lcall show_cmos" d. B0 s( ?- d9 N: K* U
8 I3 S" e* |# |* R: {
input_msg:- F' P3 }. y% k" e5 e8 `1 C
; i1 M5 @. s2 v  I. i; T- X
mov ah,0
2 w1 D  P1 k+ v
2 m# W5 Y3 }/ U. [
int 16h

$ Z1 I2 L% g' M: W
9 T! \: }$ o" G- Ccmp ah,01h ;esc

  p/ Y2 }* [/ h, G1 S7 l
0 ]6 s6 U' B$ Q2 V- V) Q: Yje exit
5 F1 b- k" V$ h- ~
! I# n# J2 r5 [8 X! L/ m
cmp ah,48h;up arrow

, e7 H. ]9 [0 M& l8 _, u' M" J( Z, R; y
je up
* r  N7 d. u+ v- H

+ s. w5 N& }. m6 Z1 Q* tcmp ah,50h ;down arrow

* {5 Q. ]6 Q$ d0 M
' ?& M' q% A* g$ D& T& S' |je down

; t# e1 i- K; d% X$ Z6 p" _& X6 K1 E: ]! w
cmp  ah,4bh;left arrow
% U% o  {3 ~% b7 K
  W& L0 V7 m8 c. b( u. q- r3 v
je left
3 N4 Z; O% ?& }" {- j+ ]
  V& a: J6 S/ Y% o. R
cmp ah,4dh;right arrow
5 x# ?: o% D! C. s$ V! t6 N" `' C
$ F0 ^( @0 ^% ]5 z1 P
je right
( D, S/ c. e! p: H: }

# a1 S' B8 k( [  i, S: `3 E2 R
3 d' [1 @; z% y/ f4 k$ rcall input_byte
/ z6 }! V" N/ |  A% W/ t

' m$ `6 @! ?- a+ _& b/ X5 n0 D( ^! }cmp bl,1
& y& S  `" |  z* i( o

5 b4 o* W# I; z! M" a) Fjne msg_loop
  y$ c" W1 q  I  }* I3 }

- a4 E, a: a! ^6 e/ Fmov ch,ah
6 A+ y2 n& L4 i& U' W

# T6 a" c1 y  Q6 |5 J4 Fmov ah,0
& g9 r7 e; }7 q' l: o  m: ^! a
& g, _2 W" d  G7 ]6 {% V1 B% X* L
int 16h
0 V: ?/ w3 K* {7 D
7 t( U- J; g6 v3 d
cmp al,0dh;enter
# @4 m2 ]( P3 M+ G% \# S

) g+ k: j1 p4 d! c, ]je enter

/ i+ v: c8 P1 B9 D( A+ @4 ~% ?3 _+ g" U$ V" L7 h% E, f8 h
jmp msg_loop

' O1 C8 e3 z, q% G6 h: L/ |- U% ]7 _/ l0 V& w
enter:
5 j% g- @0 }6 i  t; k7 X, q7 ^2 R

% \' T( v" @+ }8 R! Y" Lcall get_index

) @, f2 q- v. T" q* a$ P6 ^% B
& R  ]% M+ q$ d  imov ah,ch
/ l7 v# }! q: S9 p) X

+ `% ]; u- H( Y- |& Ymov al,INDEX
$ b. p5 A' d  [( X! A2 R
: C/ @( H9 B2 H1 n
call write_cmos
& H3 N( x6 U2 Z5 _2 l/ j4 X

! q+ ~9 [9 [8 R0 @* X
% y# H4 x- H6 u# s0 O: t' I0 t2 p
msg_loop:! W7 G6 C8 w. m2 J( J& o

# d/ C$ d7 J+ _' Q6 t. R. \/ p6 G% Z9 b) w1 z" ?
jmp mainloop
" `# @& e/ V& z  A7 y9 r  Y  M
- m5 B0 `6 g; S6 a. g

" r1 D2 {5 g3 u- a4 z. D, `up:3 E! X; A( D/ W( Z. o$ ]2 u

0 `' H7 O6 M" b) {' ]0 [cmp ROW,MINROW

0 g6 m# J7 b- }% i$ Q* N- b  X3 v' P9 p& P* A
jbe roll_up

4 V% F7 \, M2 o8 ]) w2 z5 L, V8 I' ]6 l- A/ e6 q; Z4 t  t1 r3 M
dec ROW
( j8 u. ]) D+ k3 T# l

0 g) r8 ^! A* ]jmp bypass_up

% _2 v9 ]$ [9 \: m6 ]. a  l* q5 k
3 V* y5 A, r: i! a& Mroll_up:, x' s9 X! Q- [# V' k7 M

7 d! h+ G+ f# Xmov ROW,MAXROW

) `) N3 r( R+ z
  i. @( _  l2 F9 h8 Abypass_up:
9 |& p$ M# ~' N' Z* m+ X! I
' l% I9 n5 C9 b$ z. D, s2 B$ {call set_cursor
! s6 ^9 c- I) O5 i# y

, _) P0 g6 @5 P& q1 Kjmp mainloop
+ `. |1 L! e, Y9 }/ J

9 ~9 F9 f+ R1 |down:
' o8 M# C$ ]$ W5 I, ]5 S, l
* O7 B+ ^2 I8 M* M  N' w: {; r, }
cmp ROW,MAXROW

/ D; S/ x/ \  d/ y
+ a- F( `+ J: C# A/ p) ]7 _% Gjae roll_down
5 K  _8 b! X0 F) B5 u

" t' D. S" p/ t! p. pinc ROW
+ L5 |% w% W" I1 F/ X7 e7 `

2 Y, }/ [& C' T1 njmp bypass_down

% {. {8 c1 ]. T+ P# Z. `
- _/ t1 p6 t4 u; a& y- g. u. groll_down:3 T7 b; V8 r- Y) S2 z- |
4 A5 @% i( z* M
mov ROW,MINROW
* S1 Y4 H% {. Y( K1 m
2 ?! N" ]2 B# G7 E
bypass_down:& b- p4 A3 z' R3 X
5 J3 j1 O7 \/ S2 Y
call  set_cursor

8 J/ I* Y9 Q0 c$ L: n4 k% m
; S2 D: B' {# c9 zjmp mainloop
) p$ e7 z5 O5 V
# l* C* x' L+ p$ D
left:. p7 t) n% `; R! Z0 ^+ o5 k/ Z. v2 X
5 `# ^7 R5 [; T, ?5 z2 l" @7 K
cmp COL,MINCOL
4 q- g; @! B0 w+ T, q4 }5 Q
+ D, R. @% B: F' W: r& @) O
jbe roll_left

' E, V) q* F+ Q" o& g
. M/ _  ?  k: c1 ?2 Zsub COL,3
5 d' f/ [0 k2 K  s9 f: o

9 I  g# p5 ^) Yjmp bypass_left
- t7 O7 d4 t0 H$ y) J' x2 l
) F$ Y: i2 P% V' t
roll_left:. ?, {0 `. s, }
8 x+ ~6 y4 l+ y5 q
mov COL,MAXCOL
2 Q2 d) Q0 ~) _/ K* D' z

4 d' y, P; e) A  r# Abypass_left:6 C% |: M! G/ W. X

6 F* |' [+ N' Gcall set_cursor

! d' O/ j0 e/ r  c; g0 F& t' \( M+ `, o4 _! }( K9 x
jmp mainloop

$ V; F+ o& ^4 s
( ^! [! s& r& L' I8 ^2 C! H) x/ jright:7 @) F. o4 Z6 q4 Q8 O1 G* L

* a/ O/ c7 I: R% \1 w% lcmp COL,MAXCOL

* Z( V5 o& V/ q, v# K# v2 W) B( K& W* r
jae roll_right

9 z/ I9 X8 ^- r$ ?- l
( u( ~# T- J* n! Vadd COL,3

" P5 f  x8 O# _% C& w* U5 M! [* H
jmp bypass_right
( {8 K9 D: R* @3 A
+ ]0 Z3 b& `# j
roll_right:
$ S/ K7 T: v) z5 h) M* y, T% k; T  M. U( `
movCOL,MINCOL" ?8 B: ?: E8 H. \' S. D% w" F/ D
. K$ z& z1 J( }$ H4 Y/ H4 {: m
bypass_right:5 o1 N3 ~* m# N) p9 ^
& h  J' a0 d# n
call set_cursor

, G& J/ `7 Z  H2 V( ^' y5 x6 w7 @! O5 n. Z. x* j" m+ s
jmp mainloop

2 y3 n; }( G, }8 c
. k3 ?: ]. B) l/ R* L

! ?1 a& I/ Q8 @( j# n* iexit:6 X& t  G3 s! P" o) q  t

3 u  |# m# A' X. r$ O- u: ccallclr_screen( I; v7 G! U( y7 Y, |( d% J! P

! K+ a- ~; y& ~( Mmovax,4c00h
) \3 H; N# b3 o% \6 q0 V. k

2 `0 p3 D% a+ o+ x, Yint  21h7 s) @- P$ M) r. _+ Z) L
% }8 z2 d* m( j1 R/ m
以上就是cmosdump.exe的核心架构J,完成以后觉得使用asm好别扭啊,可能是c/c++写的太多了,有点适应不过来了,以后还是要多写asm,增强驾驭asm的能力,让我的asm和c/c++一样熟练。最后开放cmosdump.exe完整的source code供有兴趣的朋友参考,source code和可执行文件在附件下载。
# F- O5 n6 P  |2 LEnjoy it!
6 I) H8 ]  S7 B- R
& |3 {& p' w0 ?7 f3 [$ L; v9 N. F( e
/ k: ?% g9 [4 I( F7 ^That’s all!* i" i4 p0 g5 H

! E) `! S; z) L4 T7 c3 Z* pPeter " K0 s, L+ C) Q1 B$ B" E$ ~
4 I/ ]& e6 P- ~  Q5 Q
[ 本帖最后由 peterhu 于 2009-7-6 16:17 编辑 ]

cmosdump.rar

3.56 KB, 下载次数: 1258

回复

使用道具 举报

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

& I$ b  Z+ @" L* ~& S% H" Z

- A# a! ~& K4 T! i1. Introduction7 r% Z1 k7 u7 _7 M
' E- n- c& e& K; K# Z0 `# L2 D' N
6 [. S! x/ g! m8 h: |8 h
/ x7 \5 {" e+ u; Q
Keyboard System看起来好像挺简单,但事实上它远比想象中的复杂,硬件上Keyboard System需要两颗cpu完成key stroke的转换以及和Host的通信过程,一颗用于处理keyboard的make&break过程,另一颗作为keyboard controller和host交换信息。一次按键过程在软件的层面上也要经过多次转化才能成为最终被用户理解的ASCII码。这个过程通常需要经历ma=>mv=>set2=>Set1=>ASCII。Keyboard System的架构框图如下图1所示:
4 u# v( @+ q4 `# C- d$ w  y4 @9 i$ O2 a  k
      ks1.jpg ) e/ G! m/ ?4 Y7 Z+ W7 H. N
这时MB中常见的架构,在NB中这部分已经被放入EC之中成为EC的一个部分KBC,但是工作原理依旧如此。
. z( p/ N" f# T2 l: I8 A& [: u) X, R* n8 ~$ M! x
2. How It Works?, C5 F, _+ v) M" x

* P3 [) O0 C- S# s8 P" i5 d那么当我们按下一个键,需要做哪些动作,才能让我们看到最终的字符呢?) N/ F; i$ Y3 c, J
听我慢慢道来。当我们按下一个键‘k’时(make),键盘内部的8031会将k的set2 scan code‘2Ch’
' L# ?* c. Q% M6 [& h6 j通过上图1的串行连接送给8042,8042会
查一张set2转set1的表将该set2 scan code转成 set1的‘14h’,而且8042会引发IRQ1通知host,表示有按键事件发生。Host将会读取60Port获取set1的scancode‘14h’,而后host会将‘14h’转化为ASCII码‘k’,当我们松开一个键时过程同按下比较像了,不过键盘内部的8031会先送‘F0h’,然后再送‘2Ch’给8042,8042看到‘f0h’会将Set1的‘14h’的bit7设置为1即94h,以表示这是一个break。Host端也会收到中断IRQ1,可是host通常不处理break code。Make&Break
3 `" x" P+ G1 m3 B) e- m
3 [0 T. [9 i. y" v+ h& w
key也被称之为通码和断码。最终host会将set1以及ASCII码放在BDA 之中。Host端对于键盘系统处理分为以下几类:a.字符键b.功能键c.控制键d.双态键e.特殊功能键,对于这几种不同按键host处理方式也会有所不同对于c&d host会在BDA中置flag;对于a host会保存set1和ASCII码在BDA之中(大小写根据控制键的flag确定);b会影响到set1的值;对于e host可能会通过中断调用相关的function。
, ~9 {4 b/ W/ U. v/ P下图2显示host的处理流程:
# D4 w2 v+ ^+ ^: W          ks2.JPG 3 n3 B8 V" [" \( J' B" R

" G! J7 m% Y* T' \接下来我将分别用C和ASM演示BIOS处理keyboard system的大致过程代码的原理是通过hook int9接管BIOS的中断处理过程,然后读取EC的6064 port获得kbc的data和status,并转为ASCII码显示出来,有一个要注意的地方就是EOI,EOI是特指8259或者8259兼容设备的中断清除指令。需要在中断服务程序结束之前向8259发送EOI指令,如果在中断程序一开始就发送EOI指令的话,中断服务程序一旦比较大,运行时间较长,可能会产生中断嵌套,严重会造成死机。如果中断服务程序结束之后还没有发送EOI指令的话,那么以后将屏蔽该IRQ以及优先级低于该IRQ的所有中断。我最初就没有送EOI,害得我调试了好久。
( m3 A9 I6 ^& [1 K& cC代码如下所示:1 K: W2 U( _+ s8 M1 o+ B' M
$ o! @2 l) Z: G4 @' d' K2 J) f
#include <dos.h>: I( q( J. |" Y4 b2 p6 y" G7 r
#include <graphics.h>- Q4 L" O' m* H; i' m1 A
#include <stdlib.h>
+ Z! J6 P8 `( C8 @#include <stdio.h>6 h1 }% C/ ]3 m3 {* t' Z3 |8 O
#include <conio.h>
- `0 R! ~4 J- H#include <bios.h>
  z4 A9 N: e0 Z: K% Z7 J, h  U; n' _( Q: b# I
void interrupt new_int9_handler(); /* interrupt prototype */- P; ]8 s$ X/ x) g1 U" J, X
void interrupt (*old_int9_handler)(); /* interrupt function pointer */9 H) C3 N$ c  Z. X6 N9 @+ _
unsigned char ESC_Press_Flag = 0;
* D4 ^5 E7 S" e8 D) l1 vunsigned char fifo[0x10]={0};3 w% I% P% W$ J( @1 e0 Z( N
unsigned char start=0;
9 i1 }$ x: W+ V- e% F7 I6 Sunsigned char stop=0;* E0 C# T' _$ r/ }* D( z
+ o/ w7 Y+ |6 n& ?1 z$ W/ P
int main(void)
8 o+ r! N/ z+ {! |$ r{: S- u  d1 _/ V/ ^- }

5 |( F0 I8 }3 x' D6 n. d6 G7 ?printf(
"Used to test keyboard set1 scancode\n");
% R- A! E9 S. a

- e- E/ ?. x- Y$ L) m! Mprintf(
"@author:peterhu\t\t@Version 1.0\n");5 o, S1 C: v9 K, L1 J+ j
( K0 i1 r" L$ d/ @) Q
printf(
"Copyright(C) LGPL\t[ESC] to Quit\n");
) R# w4 N) `+ M" h

) x$ n5 \' d* n9 n0 e: Z          /* store old interrupt vector */9 C, D+ K. ?" q* e; Q% t

& I: D1 }3 @) `/ l& M, I7 aold_int9_handler = getvect(9);

! l7 A( Y+ f8 H2 m& V7 D          /* set up new interrupt handler */4 x  ?1 T$ n- a/ q

$ b9 D6 A$ v) v: [setvect(0x09,new_int9_handler);
' I- c: S' V6 \" D; N

3 h+ }) J& h& D% A2 W          while(1)8 q: s7 `7 Y$ c7 J! C, p3 [9 c
- M" T5 T9 I7 I; I
{

9 P* ~' U$ Q: s                   if(ESC_Press_Flag)8 k' ^* B5 _) w/ j3 L+ @
                             break;
. w3 t; y; k' v. c4 X/ R9 B' Q: j
2 s2 g1 Y; p) d  r' A                   while(stop != start)5 Z# k, e$ n! \% `  @8 K

& b/ d1 H2 Y; J- [  H: R' f4 L" V9 j{
" o$ `8 T) K% }3 W

5 D+ }) q$ [* _/ I4 Y5 Mprintf(
"[%.2x],",fifo[stop]);
2 Q/ f. m+ l$ B3 [% K

! ?, b3 [+ p& ?stop = (++stop)%0x10;
2 @& u! L& f9 W$ {

. Q8 [' z* F+ C}
1 Y( I1 q) g  {% h( ^  u( R

: ]! `! x' t) p1 {& M}

8 g$ ^, I# z9 K2 k0 R0 L0 R, F  e; K8 Y
& b( }6 j9 J: l, f- C1 D4 s
setvect(0x09,old_int9_handler);
7 h! n7 t1 @. r9 t

; t* d! v( F9 E+ J1 t& g1 Nclrscr();

. c, r0 \6 Q; x2 V3 `9 x          return 1;) h0 d; F  s: U5 U
}
- S% V' N8 N  `7 u+ w' h. K0 E% z* I9 \4 T
void interrupt new_int9_handler()$ ]8 {. A# ~) P5 _2 n4 K( c$ B
{7 [2 G5 [" b  N0 |: f: }$ A
          unsigned char status;
0 n- @0 f$ {9 F8 E/ z# a          unsigned char set1;  K/ P, P" Z: j' R8 F

9 T4 e% p. v/ {# G+ |disable();
- _, X) {1 c1 ]% M; l1 b6 n

9 p, I* E' g# G2 }
% v  j5 v# U9 I/ v' wstatus = inportb(0x64);
) m7 z4 O; y! ^8 w
          if(status & 0x01). T8 F; S6 n7 I

6 H( K+ m) U7 _( P( p, Y{

+ {+ M6 {. S- b# `/ T; y
( P+ D  e6 H8 _* w2 Iset1 = inport(0x60);
5 @; x: R' \) p, D& v

7 A0 r: Z3 z; w, |fifo[start] = set1;
6 C$ f: e- Y2 p
! y3 k0 W& Q$ |9 g6 u% q
start = (++start) % 0x10;
* v+ |# `/ k! U# @7 c7 e/ o
                   if(set1 == 0x01)
+ m& Z! `+ B6 g. ]- b- F6 s- [( C# k: A. c8 _! }. [

# ^% O$ C# N/ Q( y5 G9 a; JESC_Press_Flag = 1;

  Y. a4 S" H0 w- Q+ p. Q
' v/ I/ c% J; U  U. g, s, J
' E3 n+ O7 f' [, w) a+ `
6 F9 [+ J/ C# @) ]
//printf("[%.2x],",set1);

2 p0 k% l/ y4 @' n. A  l$ ?% Z( E
% O3 Z$ g3 v0 G}
4 z* a! W4 d9 @# M2 ~! y" f4 L

1 S. A" C5 `  T6 U8 R$ boutportb(0x20,0x20);

+ X" }/ }6 n% y. H* H$ j# ?2 ?; l% \7 R( z  E2 v( Q

0 Y% z$ L2 ~% R) Nenable();

7 e, i" P* u4 A9 C/ _}
4 m+ U' a6 Z. p5 ]
0 o1 |8 k9 Q+ N: g9 G' U4 Q7 IASM代码如下所示:3 V  p1 x8 r0 ~% ?6 C! Q
data segment 2 }! v5 c& b3 V% _7 `' a) A
5 b. [- W- t) v* j  e
SET1 db 0

6 s5 L0 w! \( x+ BH2A   db [','0','0',']','$'

$ _; F7 i' j7 S1 b' P' M* l  }7 W8 aMSG  db 'Used to test keyboard set1 scancode',0Ah,0Dh,'@author:peterhu',09h,09h,'@Version  

: w; u, N% A9 x/ c              1.0',0Ah,0Dh,'Copyright(C) LGPL',09h,'[ESC] to Quit',0Ah,0Dh,'$'' ?: G/ ~. A7 E! B; r. y
OLDINT9 dd 0
4 s- _1 r* K/ j# t5 k( x) N$ E* EESCPR db 0  J7 m  B6 W1 ~# s4 s- M' F8 i

7 q4 e9 `/ g! `" jdata ends
9 {" N+ I$ [5 q- t: F* X/ D9 ~6 m$ X5 v! \9 d  K
code segment0 D! c% u8 Z" q! H2 S

& f7 U. [3 ]* Q, Rassume cs:code,ds:data
# G& {* i' I3 M0 N1 u* y: b( A' e, f# r( a% g3 _
start:+ L; Z: @( z$ M3 x* I; M

% k7 H! L  _& M5 U+ z6 d7 K/ a) w7 w! X$ S
mov ax,data

& ~' W8 `+ ~" [/ Q/ P: O; f' W4 B/ r2 R
mov ds,ax

6 U$ v: g* o2 O/ B! W' u
( ~5 e  e6 b' p" T4 p& dmov ax,1ch
* A8 U1 J0 J4 @8 `, L% {5 H$ Y
6 w6 O: I6 W) O! _4 I' j
call hex2asi
8 ~2 z7 s) Y2 [& E, z* ]6 |  D8 {
$ P+ @: m3 V+ A9 P; Z" g1 O/ t- g3 Y  s
call show_set10 O. d: j4 `7 V' Q( f' j

: b6 Y& Y6 T, s9 ~( i% Bcall show_title
" I4 N( h4 o5 ]0 @* E
5 X* V: s# m# Q7 y- m$ F
call back_int9

, m. D8 w6 q" z/ ]3 `' T# r0 k, Z" X3 l
call install_int9* z4 w9 I9 F2 d* Z
2 m! l0 q0 R  S( r
l0:
! l' d2 w1 \+ t9 d: o
( y* \( U8 n; V! _) uxor cx,cx

  d; B8 r, a" J" @
3 l  d  s. X& ~+ x/ W* Rmov cl,SET1
% k% n# }' B: K* y, Z

- R3 @' ?6 P! R+ Hjcxz nokey

8 J  v- w1 v( H; c3 V- l' o: ^! k" t
0 }* ~4 y+ E4 f6 `3 @3 e6 V$ Gxor ax,ax
* A$ \0 p3 g% `& W/ d
9 S# v4 p: E! o- G9 j/ R# ]4 O
mov al,SET1

4 f8 E3 v4 p& d. v; |6 l% h+ J1 h
2 s! [3 T# p% R# Dcall hex2asi

& m  H, y: G* r" A- r3 ^
7 T. M* V/ v  V2 E! P4 b3 pcall show_set1
/ f" T; }  X' R5 \

# [* |8 }1 J. N& [mov SET1,00h

2 i8 o% x& e2 F4 K9 ^5 o- `' q6 B) [4 N0 u
nokey:
( {6 a+ V; H; ^& Z
& y! h, E" |  L$ C1 Smov cl,ESCPR

& r( F3 P% }8 k0 n7 M3 l' W7 m- ?) ?9 J, l4 A
jcxz l0
% R8 Q7 q1 y; J1 n9 ~
  N5 s3 b9 W3 X) u4 ^0 h
call restore_int9
0 j. r+ J+ M, K% Q# I% {" D

4 J# M" ?# h1 ?% zmov ax,4c00h) c2 e) E7 g% M/ Z

5 G6 s$ K  u% k1 Jint 21h
! F9 ]; h8 i0 f( ^! Y+ \, a, [

& x% F$ I8 J8 @. E$ P;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
/ J8 Z4 w+ o# S5 B8 A( P5 L;;sub routine for store and show set1 scancode % J8 x/ b4 \- j$ a1 w- N4 r. L
;;for keybord strok maybe something error :/
% E; p( n  y8 [' F+ N' u6 D6 _5 S- y;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;! M2 o/ a9 j/ n" |6 \6 M, m* Y
0 B7 D# a0 q+ ]" G
int9_handler:
# @* q2 h1 s0 W: s$ v* X+ icli
5 d; L) _8 R9 J
5 A" j* D! A) P7 cin al,64h
6 V. v% {& Q* b1 ~( @: J; j% G# a" F
and al,01h

) A$ _* C* T, }1 w; r( D
1 B' I4 f: q# C3 ^cmp al,01h
' V  O# u& Y, H

! q: f" O, c: L* G1 f: \0 U$ Zjne exit9

$ t: S" I7 d/ R* l, K& v
) q; [5 Y; [4 Min al,60h
7 b; `# q/ P4 `6 [. t$ `" n1 N
7 o+ x; [2 R2 u0 e8 w$ S( `
mov ah,00h

6 Y# Q9 k! F! [" r7 }( \7 N  ^- [9 h, X% }( ]7 l
cmp al,01h

# t/ U- N( N6 o$ x2 r) u% G' v1 A7 u1 ^" H! k) K* {
je escp
; Z0 F7 p) M8 g7 v1 u7 z1 S2 @

! h1 F8 m5 z# Z$ o/ zjmp exit9

* f& }5 e' s6 l
' O% J/ B! w" I+ r! ~escp:
  B( C" R' _$ q9 h" }5 S' i2 O" c
! G/ _. u4 I. M/ Pmov ESCPR,01h

' f, J0 c- y9 h/ }1 h
) g/ }# E( U4 r* y; }exit9:; M& \9 L3 u0 [% b* J( n

/ m0 f8 j. c. T7 K6 k, Dmov SET1,al

$ X% j, _( `6 p8 H% G8 p8 T. z  P+ F! y5 |
mov al,20h

  r1 Z4 A/ d, y  t
: g( f$ X  T- K5 Mout 20h,al
' b9 k- m" S" B, c- r4 S
) y5 s; B' W, `1 j# X. D- t( O
sti
9 T$ d0 J5 a6 E! S% T8 C% z, O
( `& u1 w$ M/ ?' e( W- O
iret
, v# q: y. a& a8 @3 {* ]  G6 @

" C0 ~9 k& ^/ Z' S+ m( w' @

5 M; M6 t! Y3 wback_int9:
1 p1 {6 k* @8 o; B4 E
" l$ ]2 t" h1 O( b+ O  t

0 k4 N+ N; }& G- q& ^, Epush ax1 w) O  b% h6 T7 p6 M3 p, L$ }! L

  I( z: B2 o$ B  W2 d. kxor ax,ax! j% E( _8 x+ C. X
# N) m! g* v! t4 w" M0 O" [
mov es,ax
, m$ N# }2 G; a: N

6 _; Y, u, g, s- jmov ax,es:[24h]

& B) g: w( R' b9 o* }# A0 K! ^/ P' w9 q/ V% r5 L( \
mov word ptr OLDINT9,ax
: s0 _1 B8 f8 ]: _# Z

% K2 {1 y5 R  G% O* G8 f6 r" ^mov ax,es:[26h]

/ m: A8 i9 u3 o+ j( k4 B5 _  w9 ~6 f9 X( W( y* c
mov word ptr OLDINT9+2,ax
/ \/ K3 G+ z& z7 ?
+ e2 w3 U1 g5 T0 @5 m7 {' ]& x
pop ax

* d- @. G9 y" o; m
3 Z8 U; m$ Q) j6 V: V2 r: aret
& p4 p8 g5 l" B0 q1 i) h
& R! Y( A& Y* P/ l. G5 U
restore_int9:
" B! o- W- ^4 E
' X# K1 V4 P2 L$ w- R4 B& F" Q* h; B% N$ O
push ax+ n8 n' B) h$ t2 d' u: J' Z3 M6 n

- K) X, d( Z& E0 o, l3 I) \5 t8 axor ax,ax

, F, ~  j& R$ T
% {, Y  ]& v  u3 G. omov es,ax
1 v' Z: B, h" F- G$ D

3 }& O" X1 e& Emov ax,es:[24h]
& f( X% F' A3 ~. r+ D/ q
) I0 t  u3 x% @# G# i; }
mov ax,word ptr OLDINT9

# x( _) h& x$ b  W( G( ^6 W$ r# ^* O, U% P
mov ax,es:[26h]
8 ]1 X# }" r, [+ R
$ h+ T+ n' @( a8 \. u  H. N) F3 C
mov ax,word ptr OLDINT9+2
" W1 ~$ S8 y. N2 o1 w
4 N) k8 P7 L6 V+ Z) t$ _2 r
pop ax
6 z$ P6 C6 m2 R9 |: ~* {& ~4 U
( X4 I8 ?) d, x7 |) Z
ret

' o. x3 V& N, _9 V9 X* L2 x2 Q. i- [+ k) b7 T
install_int9:
  e: L* d  l7 B' B0 o8 Q  l& H' I) Q! n7 n- M* b& a: `: v& U
push ax

8 `& R6 H' |* V; V* A1 x
1 v: l) B  f; T  Qpush ds

' X2 C0 G3 L8 |4 ?# T: z# C
' o1 E1 f- o6 \9 e: M/ \push bx
+ T! {  f% a. ~6 C- n  u8 `

3 @% I% P7 B/ u: v1 M, D
mov ax,0
! A3 N* ^8 k5 Z: k) n$ ~% D  G
$ p$ ^4 T( v3 C) Z& [mov ds,ax
+ G4 C$ t7 U8 I  u, S

1 O7 Z  q; K  t6 j  i5 r' V5 ]# @mov bx,24h

9 b4 ?2 K0 W$ ?% e( U( B+ Q, w, V0 I, B
cli
1 _2 J2 v1 V, x3 C+ R' n
  T7 V' u; V- ]2 B1 i
mov word ptr[bx],offset int9_handler
+ g$ q. }' y! {3 G* I7 X( f, a% @: d, \6 `- G  Z
mov word ptr[bx+2],seg int9_handler

7 b9 {6 R8 n1 e8 X3 M
* R% R8 b) [8 z7 v& Wsti
. J" G- E- J  v4 p/ s

% C# {2 T) ]: D; F# c6 z: Xpop bx

5 g: i2 U7 b: r- K$ o- Y7 t+ P/ k. i4 @  X: N
pop ds
8 j' b8 f! N( K; b! f" c

' k8 z/ {1 p5 Q* epop ax

# H# s. W- H% q" X3 ~2 u
6 ^9 v$ v+ H) c6 Dret
. l: L( d$ m# y, s  ^

4 j9 h, b+ O$ f6 m% p( Mshow_title:
' l9 y" g: @* V& E; c3 |8 d8 J. L4 b" ~6 U5 s" g3 v' J( }9 \
push dx
) y2 N; l$ i* v- r/ K. N

$ i0 {0 d: \8 X8 P" `mov dx,offset MSG

2 F) m9 u% u% q! X$ ]1 n7 m5 N) F: Z0 F2 d
mov ah,9
1 a$ i" S* |# i' P8 q

6 V0 s' M7 K5 U" U+ h4 x- Mint 21h

" |' ?: K! L; U- r" W# W" l& [6 [% k: H
pop dx

2 y5 i9 C& r. C7 F  L
, u& H9 \, J( |ret
! M# M& {5 u6 R8 j: W3 u. X

5 J  Y! C1 e" b; ~' d& L- a8 Ishow_set1:
& F( p% h1 S0 y
- L7 c5 x! w4 }4 C% S7 h! Lpush
dx
: s* E! z  m2 K* |* F1 i0 G/ X! z' ]" ~) y( ?5 M
mov dx,offset H2A
, c7 k9 F, h4 H; n
4 E: e1 q/ v! h6 D
mov ah,9
# S+ J* O" P( t$ T; T7 r

- _9 U$ C$ L) M2 xint 21h

# N9 C1 G) g8 S* P
% N* j) W: O6 Hpop dx
1 S* l: i! n- n
  N5 q3 T: H& ?, Z6 k& P/ ^  J; h
ret
- ~* E; O0 D1 t5 Y) q& `9 U& _

, ~, e! t6 z+ ?5 P, W$ F
3 _" ]( Y5 ?1 V- _2 Y
hex2asi:
; G+ g6 B& w5 H. L1 l" f  m
! m9 h6 ]" q0 Y) I  X1 Spush dx
' W% H1 ?" N8 \0 J+ h+ {
7 H% Q, w" ~) B
push cx
2 I; i: O$ O1 z6 u
: r& C0 I) L' c; apush si
4 e. F4 e$ p2 l6 Y

8 E8 L& v$ @8 ]% E' vpush bx

) N6 {8 S7 q! J1 g% Y0 X: m9 h  V  c5 ?( B
mov bx,0

: t7 c4 q  }8 l, j$ B2 g3 `1 v& F4 U! `. T+ c
mov si,offset H2A

: g: I' s% R5 O; x2 Q
9 p) K' ]$ z% c0 Bmov byte ptr [si+1],'0'
1 L1 m7 B+ _; n

# Z3 U+ n! @: H8 h0 Wmov byte ptr [si+2],'0'

! E+ E5 C; a" j6 o7 P1 B- [- Z8 R0 s- m' Z
ha1:
2 I" l5 ~0 T3 o5 Z2 K" ^7 ]5 s! W$ `- @# {6 U) x3 U, p
mov cx,10h

, d" p& T+ d# f% u7 A& C; j8 d* u- E% J8 o! h& S5 l7 c  E7 D& b$ b
mov dx,0
, D0 a; E( Z( x( v2 @

5 d3 N5 \% d& L/ b- b' wdiv cx

+ [% f5 p7 `, w; `+ n# H0 F  T) G- F$ y7 d; V3 ~' F7 H
mov cx,ax
8 j1 b. |: f& ^) n
* }! `' m* I8 w2 D5 F
jcxz ha3

0 ?: Z( f6 ~  q5 T9 R. ~& _
9 G4 Y4 Q: P1 M4 j0 C, ecmp dx,10d
2 e" v# `. j7 @9 v
% q# ~+ y" E0 h
jnb ha2
& l$ q9 }4 N8 J' M; U* [
" s2 }, M$ I- O' p  A2 z# H
add dx,30h( P/ @, [7 q$ d% c

; g# C5 Y- x; F4 L% \3 [* V/ Gpush dx

0 m& N% c% W/ c0 s9 @) b! W0 A. K" }" h" ?2 b+ A
inc bx
1 W/ w  `/ [& k  p# ~

" Y! a* ]. r# A! e1 j1 hjmp short ha1

$ Y. X" b( t$ J3 s1 T8 F5 H. s
! p0 T' p4 w* n$ Nha2:
0 V& [, F" N* W3 c, ~! K5 r

* I: W6 |. {7 x7 Ksub dx,10d
) P" p- r6 ~9 p  f& K6 g1 ~" }

+ y, g/ _. p0 o' o! fadd dx,'A'
) {" c& q# x/ f( u8 q, d
6 h/ I1 Q. K, N0 m* Y
push dx
, h6 Z7 F  H+ U4 u5 u
/ n/ F% ]! r! z2 N
inc bx

- W- \+ f# l, k" Y4 m
% @7 D" r( X* a; U6 y/ I$ Cjmp ha1) A' u  [/ X, T6 H

( Z  ]* K4 e) m: ~& `. iha3:% c. p% Z* G* x. T7 l4 ^

9 l0 Y" |5 }% d8 }, Q# O  ~cmp dx,10d

1 g& Y2 W( t. Z
' m' L1 M' e/ Bjnb ha4
* P, x5 J0 c. O" E8 H
3 f! T4 H7 P5 d' [! W7 ~# q  U
add dx,30h
! t2 h2 g/ D3 h! V! `. A# D

$ n' d6 m, F! F$ r; kpush dx
; L4 J1 P+ B" `) U# F
3 h) E4 T; k( t# _7 F
inc bx

* g4 M  d) Z. m' Q
8 |: ^3 K# Q# y; R. \mov cx,bx

. Q4 x1 M4 C$ }+ b: [4 q1 n$ S+ Z; ^) \4 k; W$ N) ]! y6 i+ E
jmp ha5

$ Z. n& O9 t, k2 a) A* ~
: |& X0 I$ j6 H  {) W: m1 o8 v8 Oha4:: m. U/ L) L2 W5 X* H+ R# ~/ x0 j
" e% L$ s9 A0 D' f' ]3 [2 c! H% G
sub dx,10d

* P- s& l& l+ q5 w& h- M$ \7 X
add dx,'A'
) G. M4 B9 I: _" d
7 @( g% o0 n3 X+ @
push dx
+ {9 g* K* N% _9 s( h) I

; W; [7 k! W- B% v$ Ninc bx

: [; `, ~% e. i+ C/ k1 `" [
7 R7 }+ `* X5 xmov cx,bx

4 C8 E& ^% g- W2 i5 Q; w3 S. M1 u4 L9 l, w! M' c
jmp ha5
" n9 {# {+ W" q8 y
+ S! e6 D2 g1 V) ?/ v
ha5:! d9 B9 s. `7 n' }) T" J* Y
pop) h7 I  {6 Y' [/ X# s
ax

2 T, J8 v8 U+ Z1 \- @" @" z1 O
. Z9 o# E" O' |' A8 Y/ wmov [si+1],al
5 e! U: O+ |, V* D9 `8 E
9 I" E. Y3 ^) U8 H9 j
inc si
1 `  I, a0 W6 [% Q' c

( s# f, F+ N/ b) h7 p& qloop s4
. {6 F  l1 k/ ?6 b: m/ k3 Z7 [. k
" k$ ~/ U9 i1 H+ Q* q0 D, X
ok:
/ F8 G. J& ^& b
+ k& ~, F' N5 X/ V8 _  `pop bx

7 W- k: q' M, l- q$ D4 E- \/ Q1 U& V$ i5 n5 I1 `( O
pop si
- Y6 ?* s; u3 d$ ~
$ ]. \. s. H( |' J1 l- q
pop cx

  u7 a" r: g) w: c9 s3 ^
) i; e  g% j; u/ Mpop dx
1 e# j/ u' \) T1 e2 b' W

; b' U5 X/ X( f) |: D! N, f' Dret

! z% s8 K% i- z- S6 w4 y: P6 d
( O2 }- d' w* a6 x' w/ b  R2 `
" b- ^# S% L( e4 ]. N/ \
code ends6 u6 C* Q+ M" P6 g* K
end start; x1 C4 X. L' C; x( r7 O( O3 o
上述程序运行状况如下图3所示,一旦有按键动作该程序就会显示set1的scancode(没有给出相应的ASCII码,凑合着用吧J)上述代码可以在附件下载。& \+ Q; M+ n- q2 h' w: G& H4 j" _
1 z6 `" F: V5 J, g$ O' c

: R1 l* b/ D0 O4 o# @ ks3.JPG
9 M: x, ]$ o) b6 f1 ?: w; f7 HREFF:5 k  \( S  I; w7 G2 n
<<The Undocumented PC>>- m) z1 L" |0 [# D: K- V7 j

$ Y' X+ E2 W; WEnjoy it!
8 L& p6 f7 b5 M1 H& MThat’s all4 W, A2 o- _$ }. U* L1 \- L

0 \0 U- [3 |+ m( I+ T* F- WPeter
) z& U7 _$ m+ K0 j$ H0 n* T- y- F3 F) R+ x. v6 W* d
[ 本帖最后由 peterhu 于 2009-7-6 16:36 编辑 ]

KeyboardTest.rar

2.07 KB, 下载次数: 1281

回复

使用道具 举报

 楼主| 发表于 2009-7-6 16:41:36 | 显示全部楼层
戏说BIOS之Beep

( t, z' m& Y# x1 [
; N6 e  W* b; i; q1 p
1. Introduction' `$ M' ?5 w# _. B$ H  l

& `: Z/ b* s* X* N大凡用过电脑的朋友都应该听到过BIOS的报警声,有时PC开机的时候就会听到嘀的一声,有过修理PC经验的话就更清楚了“一短内存刷新失败,二短内存校验错误,一长三短内存错误,一长八短显示错误”等等诸如此类,可能各家的BIOS定的规则不同,但目的都是通过报警音获悉系统运行状况,找出病灶对症下药(有点像中医诊断中“望闻问切”中的闻J)。

* _1 g' ~/ q$ c, J8 _) x4 t
/ \- H( ?/ V  c, b: W$ O" E2. 8253/8254
+ N3 k; c4 b" }5 w+ a7 h4 x* A* f7 x5 z- |
Beep声我们都听过,但是有没有想过这是怎么实现的呢?带着疑惑随我开始探索之旅。提到这个Beep,它可算是历史悠久了,追溯到IBM的第一台PC,那时工程师们可能觉得pc功能太过单调枯燥,于是他们就祈求上帝给我点声音吧,于是声音就有了J。他们将一个简单的扬声器加入了最初的pc硬件之中。光有speaker肯定是不足以产生音乐的,因为音乐得有音调和节奏才能组成。虽然我不懂音乐,但是我知道一点就是声音的高低和频率有关,所以还要有能制造频率的东东这就是8253/8254。既然提到我就大致的讲讲8253/
8254,8253/8254是可编程的定时器,8254是8253的增强版本差异主要在可以外接clock频率不同,其实使用上无差了。8253有三个独立工作16位的计数器t0、t1、t2分别使用40h、41h、42h port去操纵,除此之外还有一个43h port用于设定控制字。三个计数器分别编程,但是在使用之前必须先配置控制字,控制字主要用于选定哪一个计数器,选择计数器的工作模式等。控制字的格式如下表1所示:
) ^6 M8 z) x+ L
- [* k0 g- w: }, s
Bit 0
* A  G! V4 `) O$ Y# \
计数值格式 0表示binary;1表示bcd5 w6 |0 [7 |  x/ Y
Bit1~3
$ n0 X  h; C" Y) E. z
模式选择% S  M2 f/ E: e& U
Bit4~5
; z7 Z4 S$ c( D- d* Q- i6 Y, f* }: d
读写指示
  W1 A2 F8 }+ d6 l5 Z# L5 i, B
Bit6~7$ @1 Z" {4 v6 R& F& p1 r
选择计数器
* ^' t+ m7 W- R/ {% ?2 \  }2 J

2 Q5 ~8 z5 H7 A( }             表 1
1 {5 \: L+ Q8 o2 O
+ A0 m, E9 F" m; {: `; z0 j. k8 X
其实这三个计数器在PC内部已经规划好了功能,基本上不需要用户参与了J2 n: T( R" B& K7 d0 d
t0:用于系统时钟提供定时基准,它的输出端与中断控制器的IRQ0相连。
, _4 o5 R8 v+ H9 Dt1:用于DRAM更新的信号,每隔15.2us刷新一次。
+ q% L3 m$ P: c' j, [t2:用于控制扬声器发声,作为speaker的音频频率。
) n. P# _1 p6 ^9 N# A所以我们知道t2用于提供speaker的音频频率,驱动speaker发生。这个部分早期驱动电路如下图1所示:8 m- W- ~7 q* b
) l2 z9 w7 n0 H+ o& W% ]

+ p; j5 k9 T. b/ B# y Beep1.JPG
+ Y0 H! l3 K" L; T3 E
由上图1我们可以看到61h PB0控制T2的gate2,也就说只有将PB0 pull high T2才能工作。另外PB1与T2的输出端OUT2经过一个与门运算然后再驱动speaker,所以PB1也要pull high这样T2的输出就可以操纵speaker的频率了。图中的61h是没有介绍过的,那就再来聊聊61h port。61h在XT系统中集成在8255之中,8255是一颗可编程的外围接口芯片,61h对应8255的port B,它是一个8 bit的 IO port,每一个bit代表的意义如下表2所示:
. l  L% U( Y7 |. y- d& u" b1 S$ }
9 z' y; q& d$ p" u
Bit0
; Z+ a" L. T$ B, L$ U, V& x
t2 gate2 控制位
7 D" b- B8 J2 x$ }* W
4 ?9 v: \, n; V! n
Bit1: X! @4 s8 g+ d$ D4 _
Speaker 控制位
- ^/ Y. S. x% U
Bit2/ W( s  }2 p2 `4 }
DIP相关# @6 F* r# j4 J6 b" T6 y
Bit3
& p$ }4 U1 R+ U4 h- A- e) g
录音马达6 ]: m* Z/ |* E
Bit4
, M, J9 \. l" F$ S8 b( X1 k7 R
RAM同步更新检查位( g/ a& _+ P; q. h7 t
Bit5& h) h7 u, S5 f% V
I/0通道检查
2 G! s9 ^8 x  l+ f* t, ^
Bit6# G, E+ g& K7 J* R7 i( F: E" L# R8 J
Keyboard 电平控制/ z+ c# I4 C9 O3 f" u2 I
Bit7. M6 [) O4 y) I* @" r8 B' Q/ D
Keyboard 始能控制
4 E. U) k1 a: }$ u: S3 ]8 U
4 W* ^# N6 ^2 v4 p( G, |
             表 2
: P: v  e/ j- ~7 b1 o# Z
AT以后8255已不再使用,port61h也使用别的IC代替了但是它的主要的bit功能还是保留了下来,所以仍然可以使用I/O指令读写61h port。& x. h- K  _! R: }" G

6 A+ I& `2 C( N6 a3 Q3. Beep~~~~~~$ G7 N. l$ _3 u/ E# T" [
/ s, G/ q2 B5 Y5 }) P2 d
知道了以上的知识,我们就来写一个“一长三短的内存错误”的报警声玩玩咯J。需要做的工作有三个:a.通过操作61h port始能speaker input和t2
gate2;b.操作8253控制beep音的音调;c. 音调保持一定的时间(也就是声音的长短)。我们逐个的实现上述功能。& p6 V. s- d. G, X7 g/ b
a最简单只要将61h port的bit0&1 pull high/low即可始能或者禁能,代码如下所示:
2 F* k4 J' E5 x9 A) K* W$ T;----------------------------------------------------------------------------
% T9 G2 _0 S* y+ r/ G: B  n
: N3 B9 N4 R5 ~, g3 {) T) u
;speak_set
$ T9 ^! ^5 W0 I! y  L) [  c;en/dis speaker input control&t2 gate2 control
( u4 u0 c! d2 w& ~4 d2 E9 N' \+ W5 A7 U;called with:cx
8 Q! q% t4 F. x2 T;used registers: ax" P- a. y/ W; z6 `3 g0 e2 j) v
;-----------------------------------------------------------------------------0 I1 |. G5 `# r$ x6 P; `
speak_set proc near( b0 O8 a4 n' I7 w4 h& M
8 e7 ~: T8 e% s3 l% c# V/ M
push ax
  _- I9 |) B3 g4 _* |7 y3 n! }9 B  g$ V2 D% i' e- C4 V/ V. q, j9 u
in al,61h

# o6 ?4 C: h4 h+ l) M) H  V8 Q5 F9 X+ W( C
jcxz se_d

3 J1 o6 ]7 `( U. D( q1 B' f, w8 M* V  ^4 I/ K
jmp se_e
3 z# B: m# _4 |* E( l- E2 B& \

2 z3 m" v, L9 Y$ Gss_d:! K- P3 k  q: o+ K1 \+ n6 `
( E$ T# c  [) c2 \" m3 F7 y; }
and al,0fch
9 b/ g) e2 L- v8 y' v# o9 k
. w. R/ {4 R* a9 ]2 V; j  v
jmp se_done
. J: s7 _6 g2 n9 V& H' i$ r1 a
! r1 Z/ [, q2 }* A& T" |# S
ss_e:. O# |) Y" [0 m& P6 u8 c1 ?
) K/ D$ {( \# D
or al,03h
: B9 p- S  l* d: b3 o% p. V

. a* s  ?( [! t# u3 gss_done:
8 }# ^( |* o2 V( \' X: |
! ]6 f% \0 E3 E0 l% h( P& cout 61h,al

% }& {: H! W" W4 m6 j) g
7 j3 c% N+ V# I; p" G4 @pop ax8 D4 x/ m3 O# }' _4 g* j. r
5 K# a. a/ q7 `" j& t+ o
ret
7 [" a2 w& v5 c! s
: t8 m( P% m5 @1 s
speak_set endp
+ W' J  y0 C5 Q# Z6 E

! a1 V; a$ Q! E# o: j" i( a$ y8 d9 k
b就需要设置8253计数器2的模式工作频率,操纵8253的步骤为先向43h port选择所要使用的计数器以及工作模式参数类型等,然后再向42h port装入t2的计数初始值,代码如下所示:  W9 Y0 l( t' W  E1 T. ?
;----------------------------------------------------------------------------: {7 W2 V1 D( q" G) @1 A+ |) R

9 a7 {2 w" b3 d& L. r1 `& |) b* V;t2_set
4 ~  P( C) L* i- v;enable t2 & set work mode & out 2 frequency
: u6 U: Z8 v; v/ P$ h;called with:di(frequency demanded)
3 C3 g: v; w9 O$ v4 E0 I/ i$ A;used registers:ax,dx5 t. h0 M* O: b
;-----------------------------------------------------------------------------7 e- z5 j4 F' ~$ b% x- l
t2_set proc near9 j$ m9 C+ ~% U2 @
9 Z3 n0 @* Q4 J% R1 a( g
push dx3 F; b2 v- b  s- Z# _8 f* p
. X/ |/ E* S, e# u( ~/ \7 l
push ax
- P$ f4 S3 O9 M3 b" G( M9 u

$ O* D" Q6 R) v1 M8 y6 Qmov al,0b6h ;t2 lsb,msb,mode 3,binary

4 u" O* s/ T5 _, n, x& S) w9 D- H: O+ K5 \, ?  V/ R$ L
out 42h,al

' W0 b0 X: V+ I) ^! R% ~$ k: R0 I3 X9 ^
mov dx,12h
0 D+ a9 s" P5 M6 ]8 w+ F  ]# F- G% ~  ^

: Z: b& V' E* [  I% {- w7 y" i  bmov ax,348ch
# ]# {; u1 l0 a9 P
  }/ t* E& C1 B* l5 _8 r
div di
, V- j( t' c; A+ s9 p
4 o) ?$ x! ?3 B5 ~  l9 h6 V
out 42h,al

& |( s  X6 b! B# H
" B& I; Y9 k  wmov al,ah

& v+ A3 b( @# |. F2 T, l7 y3 U" J* O/ f4 \3 L6 F8 y) a
out 42h,al
3 @. r$ ?0 T, c- \/ A4 v" N5 C
8 q3 D; y/ H' r8 ^; w& O8 [  \# i
pop ax
, T" a9 B% c- `- N- p" n% a$ ]* Z8 L5 {) @0 P/ s) C' O
pop dx
+ ^1 R: K; }* L: ?3 y# a+ v
' y( D, }+ e, T# R! g! W; H" K
ret

8 r6 W+ j, T9 K; M; Y9 \, A6 i
- E" [5 g: x; \$ G% F( x6 Zt2_set endp
+ U# b, o; i+ P- M5 I/ ^& C
7 X! j" |9 b; dc可以通过执行loop达到延时的目的,可是loop延时和处理器的类型频率有关,不同种类的cpu执行同样指令所需的时钟周期不同,就算相同种类但是主频不同的cpu要达到同样的延时效果计数的基准也会不同。那么有没有精确延时的方法呢?书上给出的答案是通过检测61h port的bit4 ram刷新检查位,每隔15us该bit会发生一次变化,所以检测它可以获得比较精确的时间(我猜测这个bit会和8253 t1同步变化,因为t1的输出脉冲用作DRAM的刷新定时信号,而该信号要求15us刷新一次)。延时的代码如下所示:6 L$ E8 C$ |, Q' \7 f
;----------------------------------------------------------------------------+ m/ n: {+ A2 j& j

  c( G& Y4 \$ a3 z) L* U# s4 Y* ];delay
: J4 ~1 \- V& f) o' V;delay time base on 15us unit" R  C0 \; ^/ y  E1 r% }' A
;called with:cx (counts of time unit)
, F8 z" V: }6 Q- c+ T) K;used registers:ax5 |" G+ E3 l: Q/ m1 U5 L) \
;-----------------------------------------------------------------------------( b, s2 q+ j, H
delay proc near
9 u* _7 r& ~0 I, [5 S2 h& B8 L) Z- H# x* I/ T
push ax
. V0 N) J, ~# I9 Q# r; J& n; u, K4 U+ I0 ?5 n
dloop:
/ j5 l' E( X' `; n- W( i" x  }, w2 x4 s  `; [
in al,61h

5 I2 T# B1 W0 h9 ~" a" f! U8 r" C+ J4 v/ a/ _! a) W$ o* J
and al,10h

9 z" K7 s+ [+ n4 [! u4 B- T, I& z9 b
! @% L  w2 y- n& l9 s3 V$ [6 n3 Ncmp al,ah

/ \2 Z" j5 i  O1 S" \+ v, e4 j/ ~7 I8 @. M! t5 d  r
je dloop

6 h9 G6 g7 G( u8 D( v2 a2 F6 B; J6 H1 U2 B
mov ah,al

$ N( q5 d, B* {3 h# }' P7 m+ `& i' u& t
loop dloop
7 T+ E9 q3 d$ k0 p
: ~' B: _* Y( C. ^  }, k8 t) t
pop ax

! y( C- ~5 e  \! Z7 Q3 g* h, [: h% r
- z/ {9 ]/ V- k) aret
% W4 t# T* o4 a6 `7 _% m9 @

6 ~2 q, M4 x# o# H" u9 B1 R" |delay endp
& X, I% u7 o5 G% [! j+ h4 J/ p$ }, c# [+ d$ S
以上就是beep的主要代码了,最后开放完整的source code供有兴趣的朋友参考。
" l2 s. Z2 Q; O
% n# a6 A( U- ^& I* e) OREFF:' ]/ A* J1 |# }

# e- U1 q4 Y6 T* g$ d# ?  T2 \! f6 V+ W: c% M. Z' B
PC硬體元件控制詳解
% ~! Z8 g/ Q3 A. W7 N( s
$ p/ G: n% p5 Q$ ^; X《IBM-PC汇编语言程序设计》
* B6 @! F9 @1 b$ v, v# h
+ V# l6 Z( B( G

0 w2 d7 @% s  E. o5 Y, r

0 z( j7 Q+ X3 y# v) GEnjoy it!- i( t. d' r& V. v. M: Z2 r
- G3 W: S4 |! Z  _0 U( d- R& _
) L" U' e& ?2 _) k
That’s all!
6 s0 C% |/ y- r$ i; N, J4 y- S/ g( ^3 C) q: `: d% O
Peter
$ ?# T% ^: I, T- M5 S
" }/ ?1 b0 z6 ]+ T9 E[ 本帖最后由 peterhu 于 2009-7-6 16:47 编辑 ]

beep.rar

945 Bytes, 下载次数: 1260

回复

使用道具 举报

 楼主| 发表于 2009-7-6 16:50:33 | 显示全部楼层
戏说BIOS之PCI Scan
: Z$ `) j: a) b# H

+ i* N0 s* P* w, ]+ L1. Introduction/ V8 ~6 e, W* q. H
4 q* Z2 {* e/ ^# g( x- H  u
PCI由intel公司在1990年前后开发的,后续经过若干年的发展以及标准化,它已然成为server&pc上的标准总线。PCI以其出色的设计以及不错的通信速率在计算机领域攻城掠地,不断的取代诸如:
MCA,ISA,
2 q3 C' r" w. A# hEISA,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。
# m5 k6 J" g2 p" A( T
0 I8 L  w6 k7 z8 S( C2. PCI Arch: ~9 L# f# V2 e2 n& [6 i& [1 Y

( _! K! W9 J/ o8 ~可能是软体背景的原因,因此我看PCI spec也会习惯性的使用软件设计的视角去理解PCI的设计(我觉得有关设计、架构的理论应该是相通的,正如软件中经典的design pattern的思想来源于建筑学一样)。我的视角里PCI同经典的接口编程或者插件式设计非常接近。接口本质上是一组规则的集合它是对同类事物行为上的表示,它的主要目标是实现相同类别的不同对象行为上的多态性。面向接口的编程是OO思想的精髓所在。它的好处体现在哪里呢?首先它增强了系统的灵活性,只要遵循接口定义的规则,系统的底层实现部分就可以灵活的替换、扩充如:PCI总线定出了设备的统一的硬件接口,这样遵循该接口pci device就可以方便的扩展入系统;另外相同的接口可以接入不同厂家的设备就像同样的sata接口可以接三星的光驱也可以接LG的。其次规则给出以后,实现该接口的部件就会有共通的接口但是不同的实现,如此系统端就可以通过接口灵活实现对部件的操作配置。PCI定义出了三种规格的配置空间,根据配置空间提供的信息系统端可以方便的识别设备的种类,功能甚至于厂商和版本号,获得非常丰富的系统端知识;而且该功能也使得设备可以动态的配置资源进而能够做到plug & play。

; b. c9 ~: c. n) n& l8 C) y3 P" m( L+ h  {" f5 \
3. PCI Scan
: Z* k% z! Q! t) h. M; J
) _& ^1 Q( Y. d% D* a
& G$ ~$ E5 R9 y1 q, Q' \PCI Configuration Space是大小为256字节的一块空间,它由header和device specific两个部分组成,其中header部分是固定的而device specific
部分则是与device相关的,不同的device会有不同的layout。配置空间被用于配置,初始化以及灾难性错误处理的功能。下图1是type 00h Configuration Space Header:. @2 r/ P5 D3 z" g2 N' |* x0 L1 G! j. a! P
! [2 n3 |, F& x: q1 a
pci1.JPG - ]4 V- `. T/ h6 Q
5 T4 |7 F# t. x& S7 w
图1

& c! U) i* x  L. UPCI Scan的重要任务就是读出该256bytes 配置空间,那么如何读取这部分的信息呢? 有下述两种方法:
  I& [: f0 o. ]6 \) E1.使用0CF8-0CFB, 0CFC这两组IO port存取PCI Configuration Space。将总线号、设备号、功能号和寄存器号组合成一个双字送到配置地址端口(CF8H-CFBH),然后读写配置数据端口 (CFCH)即可获得配置空间的数据,下图2是配置地址寄存器的格式定义:
2 o  j4 v2 V: ]% L2 {( W* Y6 g* }' V0 u# E' {; @
pci2.JPG
7 \, @+ `1 i5 w1 c; P& T. N' w- _/ `5 _. M; T1 Z) O' o
图2
+ C2 p+ l" }: R( x& c, g
所以我们先要build一个config-address然后再去透过端口存取配置空间。4 r6 S5 U% H5 x( t9 L% m
下述代码用于build config-address:
( W* @  z9 X/ E( N: q7 f7 q;----------------------------------------------------------------------------( u4 L: o- o3 I1 w! s* n
;build _pci_cfg_add:: `& T) h7 `: w" `1 [" y: {
;build pci config address
3 ]1 X8 i3 g( t# ]  B6 k
;used registers:eax,ebx' h. r( j: U: ~6 h! t  h* H
;-----------------------------------------------------------------------------0 X: Q7 D# z. k2 c5 p8 S, O& G
build_pci_cfg_add proc near
/ `- }5 B! b( F
, S4 |+ \# o, y% ?6 S# [2 xpush eax
6 k# f) c) i" S, m
0 ^- M& b3 P0 r
push ebx
0 w$ F/ G" I2 I9 r; a7 E% ]0 _" ~. p

2 g2 R6 o2 ~- H/ t6 m- \xor eax,eax
1 \9 b) e! J2 C4 M1 `. s5 L) Q5 b5 @: g4 a2 Y  \9 M& ~
xor ebx,ebx

0 b+ s- V8 N, n4 S+ o& |5 w9 i0 h+ I) ^' v
mov PCI_CFG_ADDRESS,80000000h
2 P$ w0 `/ j: K+ o( n2 ?

* e. f/ z8 `! B8 f& xmov al,PCI_BUS_NUM

; W+ y* G, ]8 T; ^  I. v4 \# n1 J# ]# v" [) I: k3 x
shl ax,08h
1 K& J, H$ R" s6 z- ]# K2 Y+ j# M. d
  C( b4 h8 h2 i5 ^. p
mov bl,PCI_DEV_NUM

9 \2 ~# N9 d- ]( _; a- Y9 w1 c8 c9 l# e) }* u+ T
shl bx,03h
8 t2 D# m: N3 w
6 N; q( p# B: ^& d2 P$ T6 r$ T
or ax,bx

3 o. G. B% ?; p$ i' A2 I6 e+ r3 v( v" |) V" L
or al,PCI_FUN_NUM

& q+ c4 n* Y! h! K1 P3 M' j
4 h9 o2 `4 z* C0 O; i9 U! f' S3 }; y# P; Q6 u4 n
shl eax,08h
8 Q/ @2 m% ?' G& ^* Z0 y* E( ^

: T, v3 o* A. Lor PCI_CFG_ADDRESS,eax
" T0 M1 G2 T9 K) _) `  U
" i7 m, t3 e1 F  {2 ~+ Q
pop ebx! {+ A1 W3 ]3 f4 B2 e$ f' d& u
9 O+ }6 B8 W, v& v9 _! [
pop eax
7 E4 F1 O" Y1 F% N
4 o! `/ ]2 l$ @4 u2 i, O! Q+ j
ret
3 T* M$ c7 h5 W

0 M, H+ W4 v+ p, B/ p* Qbuild_pci_cfg_add endp' g/ B6 a, g0 g: R& l0 m; K: K# B
" l& `# u. s) I. U# [3 u+ }

8 F$ a: z9 X) J8 Oconfig-address准备好以后接下来就是透过IO port读取pci configuration space了,下述代码演示读取的过程:
9 Q3 A# e# ~& u% T- k4 I;----------------------------------------------------------------------------
7 N1 ^0 L& p) }/ v0 f
;read_cfg_space
# _* {0 g) Q# Z- ?% b) R* s;read pci config space use io port
8 p- Q  W  z& l6 ^# y
;Called with:NULL7 o$ I( X/ p1 r1 [8 C* `6 b' _6 @
;used registers:eax,edx/ F1 G1 B3 U, Q- b
;returned regs:eax7 u* D. l( S5 i; A: T: E
;-----------------------------------------------------------------------------8 H7 Z% H8 R& M" u* n
read_cfg_space proc near
& B5 k* U# p( V; Z  r9 ~! i6 P! t( S1 i  H( C9 C8 }
mov eax,PCI_CFG_ADDRESS

0 o4 Z5 R% _8 ^: B. A8 {$ r' r" V) o5 b- m
or eax,edx

  p6 Q. I; S3 |; t! _
1 [1 z; L0 m" \* [+ ~  n, nmov dx,PCI_CFG_APORT

7 `$ b" I4 {" U; t4 N. ?
: x+ k5 ?# _4 M' _0 _out dx,eax

+ ?; a/ _  x" r5 d2 E5 K3 g
. Z* d4 c% l0 u% [2 L) O2 Amov dx,PCI_CFG_DPORT

+ ?  }' N" k0 B& `- c) i2 m, i4 t7 Q9 l8 U, q
in eax,dx
4 H' m" A9 W- s- u3 Z
* d* O  Y' D% B# x- o# S6 B
ret

* l$ s8 ?% ?6 S1 {$ m8 x. [
; G# {! ?4 [0 ]% [9 w
read_cfg_space endp$ L/ n# c* ]. ?' j5 g& A

8 \  n1 W5 u7 t( r& ^6 R7 _: s$ u- r) s% T9 F5 W
理论上PCI bus支持256条总线,每条总线支持32个device,每个device又支持8个function,所以我们组合出上面所有的可能就可以遍历出所有的PCI 设备了。可是实际上PC上面PCI 总线通常只有1条,最多也不会超过四条所以我们只扫4条总线就可以了,不用做太多的无用功。有了前面的准备,我们就来实现一个类似RU中的PCI scan吧,下图3就是我写的pciscan运行的状况了:8 f0 p, I" S4 k' F
  L( C' y4 r) M: ^' P' p) T5 z
       pci3.JPG                                        6 ^( K7 Z. k& i5 Y  t

7 O# @+ h# K) l0 y图 3
0 R6 B/ |' [4 C) i
在该界面下按下esc就会退出该程序;移动↑↓键就可以选中device,然后敲enter就会看到该device的Configuration space 如下图4所示
5 V1 m0 g* Y5 j# }* M pci4.JPG
" G0 v0 x9 o, [$ u1 r. C$ s8 Y% K6 O" b* ^3 w3 t, Z
+ T% U! Y8 t( T6 f/ |& z9 e
图 4

+ {6 y# j. s& a) G1 M当前界面下如果想返回到上一个界面只需要按下F6就会回到图3的界面了。# G* a0 S. z* {" ^$ o& @
4 A8 c& l+ b) v: Q. T
2. Call PCI BIOS int1A同样也可以获取PCI device的信息。其中AH=B1h,AL=function id所有的function id如下所示:% J8 t. I+ J) N
01h: INSTALLATION CHECK
/ u; ^' m/ T3 q% H- l1 }02h: FIND PCI DEVICE
/ q0 {. U. |  M) Q03h: FIND PCI CLASS CODE* V2 {; R# i2 |( v
06h: PCI BUS-SPECIFIC OPERATIONS9 H. F; g4 t# ?% d/ C
08h: READ CONFIGURATION BYTE  O$ b0 Z% F. T  h+ g
09h: READ CONFIGURATION WORD
9 }  ~  O; |  O0 F$ v0Ah: READ CONFIGURATION DWORD( P' @. E1 }3 u
0Bh: WRITE CONFIGURATION BYTE
3 \6 z7 [' ]6 F8 t0Ch: WRITE CONFIGURATION WORD3 |! F+ N, t3 m" y) c
0Dh: WRITE CONFIGURATION DWORD
7 _4 p1 s" y( }0Eh: GET IRQ ROUTING INFORMATION9 w6 W, E% T) ^4 K2 D' @
0Fh: SET PCI IRQ
. h8 B9 ^3 T. W% L% f" o  b4 o' @1 M81h: INSTALLATION CHECK (32-bit)5 Y! f4 y/ b) O+ r% \- X
82h: FIND PCI DEVICE (32-bit)9 M+ N/ y0 W- s$ d
83h: FIND PCI CLASS CODE (32-bit)5 h2 L& r  L! r2 N/ y
86h: PCI BUS-SPECIFIC OPERATIONS (32-bit)2 `3 e) t0 W! d( }. u4 U
88h: READ CONFIGURATION BYTE (32-bit)
0 i% n! P8 h' a" u2 s# T( S" c89h: READ CONFIGURATION WORD (32-bit)
, _9 l  b! U7 e8Ah: READ CONFIGURATION DWORD (32-bit)0 z" P8 G. U. G$ j
8Bh: WRITE CONFIGURATION BYTE (32-bit), H" Z" a" j: m
8Ch: WRITE CONFIGURATION WORD (32-bit)
3 J/ }( B5 O' U& w/ O8Dh: WRITE CONFIGURATION DWORD (32-bit)
+ z9 r. v$ x/ Z8Eh: GET IRQ ROUTING INFORMATION (32-bit)
" y: w  M; N0 ^6 r0 `" J) i+ t8Fh: SET PCI IRQ (32-bit)# M  N- t$ r7 Y  c- l8 r9 f: k% {+ T
我们使用function id 09h就可以从configuration space 中读取出一个字,这样的操作明显简单的多了,只需call 一次int1a中断即可。下述c代码演示了读取Vendor id的过程,如需读取其它部分只要算出具体config-address即可。
5 P( ]! j) P# n
% t- I) f* z6 N1 X' h9 g#include <stdio.h># `$ \2 B8 U! t0 L+ H
#include <conio.h>
6 U1 `2 L  r& o) o5 N; J#include <dos.h>+ }+ @" |- ?& @7 o7 e

0 z4 ~  Y: f% pint main(int argc,char** argv)
  z) W2 h; [9 H! z) p{$ Y/ E4 W( d* `: q* L% [+ m. W
6 \4 L' ], E! y; w5 Y2 p
     union REGS reg;, b) X9 M0 b7 ^9 i9 A
2 X  z6 e' F; m. B, a7 I
argc = argc;

! F* H) |% q, \9 Z3 W7 A0 v! X6 s/ W% J
argv = argv;

9 `. [$ I- h* T" e9 P8 D. K& R. e4 z( `8 _
reg.x.ax = 0xB109;

; E* X; F' R! Z; k& x  z, y& h% N4 Q+ J; ]: f4 F+ ~, ?" ?
reg.x.bx = 0x80000000;

" s; a! _5 N! [: {# D4 c- a- q
/ {3 u: _5 q  W+ {+ A, Z
/ }0 v, C. I# p' [# areg.x.di = 0;9 s, s  G# ~7 _' m% U. E
3 e; D2 t7 C! D5 }6 s; {
- g' }1 ]/ {4 b/ F9 Y  ~
int86(0x1A, ®, ®);
# Y/ L, }# [- W+ P$ z) a

+ w# L6 |# h( h  }     if(reg.x.cx != 0xffff): t8 A& Z& J2 H" A9 U6 A
7 n3 Q3 _6 t8 j: Q# n% @+ o4 i8 F
{

: O$ E* h% Q" o8 G6 c0 k2 w4 ^: G- F/ Y% x
printf(
"Vendor : %4.4X\n", reg.x.cx);
. B0 V& }5 `4 E; ?6 M5 x6 l
3 G8 @( ?; N8 r6 C( z3 P
}

! j# T/ P+ H5 A5 |8 r' A
4 }8 c/ O  Y/ i     return 0;- K: g+ d& T5 v0 v7 ]4 y8 d
}7 q6 c/ E& r5 L1 m, n

& t) f7 {! Y+ I# s# k* ?2 T程序运行结果如下图5所示:
0 F! Q( [; O  q# g( U
! K. `9 s& l* H$ ?% n2 z% { pci5.JPG
4 K; _( J8 V! u' _1 O  u9 B* s1 \0 u' _
图 5
9 @0 p. d5 w3 l* S- T
* A* y1 L# T" L$ O
最后依旧是开放完整的source code和可执行文件供有兴趣的朋友下载。3 K8 t2 T2 ?- ?/ m

0 K" e( g2 W& o

* x/ ]! C: c) L8 wEnjoy it!
2 o7 P/ e3 ]) Y0 X$ p% @7 Z* ]7 Y, l- [7 Z9 X5 s3 B4 b
9 o3 Z, Z; r* F) a9 t& |" |
That’s all!. \' }9 P) Y5 G! w
0 `. H1 W$ T" ^1 l; k: x) C
Peter
4 b+ @- Y, {5 i4 l& Z" q$ V8 t4 Q1 a6 Y5 y: i- h; b4 r2 s
[ 本帖最后由 peterhu 于 2009-7-6 16:55 编辑 ]

PCISCAN.rar

4.69 KB, 下载次数: 1383

回复

使用道具 举报

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

使用道具 举报

发表于 2009-7-7 13:35:14 | 显示全部楼层
Peter Open Source 的观念很强啊,想当初小弟刚开始接触BIOS的时候,要是碰上你这样的大虾,那该多好啊...1 i% y. v8 P3 }# R5 ^+ U
UI 就不用画那么辛苦了
回复

使用道具 举报

发表于 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

戏说BIOS之Clock Generator

# y* F3 Q1 k6 r) R9 c

8 l) s8 t0 W. `. C8 n8 K- d& ?1. Introduction
+ w0 ]" F9 W$ {* J) C$ j) x& v4 s. e( j
Clock Generator是主板上面一颗极为重要的IC,说它极为重要一点都不为过,因为Clock generator负责提供主板上的clock, 一旦Clock Generator除了问题,板子基本上就完蛋了。Clock generator供给的clock部件有CPU clock,PCI clock,AGP clock,PCIE clock,SATA clock,USB clock等。
+ R' B# g! F' V, G! z7 v9 s% |
2 }- ^% m8 A8 P7 X) A
# E, W4 m8 s6 J+ o! o  t1 k' H
2. How to work?
# r8 p" [6 v6 ~' i7 r  ]/ d( s2 _. K; k4 \1 M1 \3 R$ J2 T
Clock generator 是一颗IC,它有一颗外接晶振,内部会有锁相环放大调整电路,可以将外接的晶振产生的clock放大调整然后再分频输出到各个外围器件和总线,提供器件和总线工作所需的clock。Clock generator的工作原理如下图1所示:

; `' D9 Y/ l+ ^$ \
% u$ X& ~1 `8 T2 A2 R
cg1.JPG ' s$ d* s& ?  {* e# Q
Clock generator通常是一个smbus device,接在SB的smbus controller上所以通过SB的smbus controller,使用标准的smbus protocol就可以存取Clock generator上的configure data从而达到配置各个外围器件Clock的目的。鉴于clock generator的重要性,所以BIOS在非常早的阶段就会配置它(boot block阶段),让CPU、memory等的工作有一个稳定的clock。下面我就以VIA平台为例演示Clock generator读取过程:
+ H/ K5 j, T; g3 J2 t8 @! \! O
1 @" j- K- ?6 Q
  • 首先要通过PCI配置空间找到SB smbus controller的base address。
  • 查看Clock generator smbus slave address。ICS9UM700 slave address:42h
  • 透过SB smbus controller下达slave address & protocol完成clock generator数据的读写。

0 z. d3 E+ [0 g) d9 i' Y5 C7 e! W下述code演示了获得smbus contoller base address的过程:# F; W( ]. G1 }% }9 u  @
;----------------------------------------------------------------------------: o1 t& N+ l6 i6 m; C
;get smbus base address/ |: ^" ]; w' e) I; ]" d5 w7 D) G
;used registers:eax,edx8 a, w1 f1 ?- j! A, y: Q* H2 A/ Y
;called with:NULL
) V2 |/ e, V0 E. }# N* J;-----------------------------------------------------------------------------
4 @  b3 ]& f* u6 \9 {get_smbus_bar proc near! d8 {3 Q" M5 a

" V7 J" T' \# j# d' `" ]  K! Epush edx

9 F% E. y2 w; I7 T, U( a6 p6 ^6 H  m' s1 @# ~
push eax

8 Q! a, t" e+ G0 s2 W' K$ Z
" C% b. v. }) l: a# n# imov dx,PCI_CFG_ADD

: K: I" n- u$ o7 t2 I. ?
1 G, v* v  m! i% H% w7 w2 c% ymov eax,PCI_SMBUS_ADD
  J1 k4 D5 x2 c& ?, j3 z- A

' J9 v- l$ Z- m2 U& W2 m% pout dx,eax
4 ~5 \! C6 |* v1 M% v+ G

) `) g4 x& i% o; B) B2 E3 h$ J& U7 |: cmov dx,PCI_CFG_DAT

) M: N+ a" o/ K, O: D
2 d8 V9 h8 B7 _% o+ ]' kin eax,dx

9 |: H. _. H  a+ \# s6 W
# |- V8 S* Z+ Jand eax,0FFFEh
- l" v: w# y+ c- s, z

. o& H( |- W' q% }( ~mov SMBUS_REG_BAR,ax
7 p, W5 v0 _5 r- c, a, @
0 Y! W1 y9 @7 _  i. N( {# s
pop eax

/ P7 q$ F0 y6 g2 T1 Z! `, S4 e! v( F6 G8 z: a8 E% `& Z7 G9 w
pop edx
, F* f7 u& D7 ^( u

/ J4 a0 T/ F3 `. Z; D  ]ret
: Z  y1 k2 [: ~; \
get_smbus_bar endp1 S1 c3 O' W2 n6 F
8 _- ^' z3 U  d  u8 o- `* T1 v" y
下面的code演示使用read block protocol读取clock generator configure
$ p! i4 l, d4 Y5 X* B! V; s) adata的过程:* U( h2 @8 S' [' v$ P- ]
;----------------------------------------------------------------------------
" z5 c: W+ i1 M; j( w' w;read via clock gen data by read block protocol. ?( ?% X* r, ?$ u( e: |
;called with:NULL
: f: A( c* x: I# G: Y" H;used registers: ax,dx,bx,cx: r' r9 D; A/ R' k5 T

5 T! I9 d1 M. p+ r" {) _8 x;-----------------------------------------------------------------------------) Z' r, b5 o4 L( K
read_via_smbus_block proc near$ L4 Z% L5 E2 ^  p  x; ~

' D0 c$ Z7 J$ Tpush dx
8 v4 H9 t. W; h* @) w

+ N2 g  o1 H' E7 upush cx

" \$ L( T6 d/ X( T! Q
9 j$ _9 C5 i4 e8 q: Bpush bx

) l+ L" `, b. u! l) p! _
- `9 B5 C4 ]7 d3 Apush ax
. r7 ~+ o0 K9 c# P+ G

5 F+ A6 p7 M1 _. K/ _
# Y( V5 S* f  `6 }- r/ pcall get_smbus_bar

+ c6 E1 w: f; u/ a- j2 T# I4 [! V4 d$ b- m+ N0 h. K  p
;reset host status registers
3 Q0 |8 B+ a6 @6 m6 {% {
9 f' d) N4 f4 S" O9 w, s
mov dx,SMBUS_REG_BAR
( v2 C# L  I( l8 ?; h, Y( e

0 M4 \/ U* F+ A9 _or dl,SMBUS_HSTS_REG;(00h)

: ?# x; `# b4 |4 E. b6 f7 O% P, F9 M+ C+ x4 i7 i
mov al,05eh

% ]0 W# d4 @/ S) ^% o2 p- P  p7 X( d  n8 S( A& c- C
out dx,al
  n- ^4 N: T' D( q% a

- R+ i2 w9 l  e6 C
# y$ @, K" [# i8 H/ U6 B* _' T1 J$ z;set smbus slave address

" n( c6 J) P: x8 t: M* B! l
5 D3 {6 u9 j- x" hmov dx,SMBUS_REG_BAR

( A9 e- m1 x  `% a' Y' S
- O- `8 R  u& o5 s" Q, jor dl,SMBUS_HADD_REG
0 [' A# J, z, I0 E

" J3 |3 p+ E+ J( f/ _, hmov al,SLAVE_ADDRESS

. H3 S" u3 ^# n/ w: o! t, Q. W; O8 _- D7 F  W# L+ v
or al,01h
- ^# h: M3 `" j* @6 n5 J% i' G

. k8 n1 I6 r7 L/ {1 E; F, Pout dx,al
; [9 {0 b3 }9 p% J7 I6 }6 z4 i

" Q3 ^$ m" T' s; L; Pcall io_delay

2 c# V7 O1 M; I4 H
2 ^  x. c  u6 _# o: J2 D0 N4 B2 [( G% k! z
;clear smbus status
6 U7 L, Q' c7 G* f, L4 B/ e
# Z) o( [; G# [. r
mov dx,SMBUS_REG_BAR
* ^) d) }# w4 ^- [) b" Q, R3 v  y
) l- H: x  s6 o/ ^9 J
or dl,SMBUS_HSTS_REG;(00h)
; I3 C& I; [9 e% t
2 b2 ]: D4 _5 k: F
mov al,05eh

: _$ l+ ]/ h6 Z+ I1 l' M+ N  _0 C
4 P* A  p2 }3 u* w1 `; K- x( Jout dx,al

7 U- _  p7 k1 A9 j. y8 ~$ O7 O# |1 y% J! u- l  d1 p0 f
call io_delay
) y0 A2 H' l4 `3 N  ?- r! x
8 t. Y- r* E9 G) B

; |3 l; f" \& N0 L4 x, ~1 [8 u;clear smbus command byte

- X! q5 C3 D  N& \/ T' A- I4 N& N2 ~# r) _
mov dx,SMBUS_REG_BAR

) L, \8 n* c7 j' L; h( p- b7 L  ^0 m, V& n2 r- N
or dl,SMBUS_HCMD_REG;(03h)
% P* Q3 w) i, B. P9 u
0 y  M1 x7 I! P0 f- ^
mov al,00h

+ J0 C8 Y9 |& s1 s) X7 M* ^. C
/ ]1 D5 @: }/ o3 o# P7 ?4 ?out dx,al

) R1 q' J& L0 t3 }, R2 S+ M
# }' n# K! b2 b! _
  K4 U" e, W$ Y0 D7 }/ M. [;block read protocol

( c4 Y7 T8 c& N/ L9 A% |" T$ |( H
mov dx,SMBUS_REG_BAR
- v  q# d  @! y3 k

9 S3 p* k' q7 G" a5 uor dl,SMBUS_HCTL_REG;(02h)
) C3 W) P# v7 i" R

9 `8 W) h. n  i8 F; S- P8 ]# Vmov al,54h

2 A" k$ H! K7 o  [; D2 i& h: ~
2 @- P- X, ?; Wout dx,al
2 Z# P" n& P, C! p( F! R* E" E
) a4 D1 M+ j' H- W0 Q
call io_delay
; i2 F5 ?4 n( Z3 O6 j% i+ r6 P6 X

/ H2 i8 X! ?* l1 ~& F
' T. G* x8 P6 p  y;wait for smbus finished

/ \5 o9 }0 _* @$ H3 ?" O% U% ~# \! d4 g! J( u
mov dx,SMBUS_REG_BAR

& y: ?5 v) v8 v/ i( f
8 {0 ^4 N# ]# K1 e  F( F/ por dl,SMBUS_HSTS_REG;(00h)
, H0 ~. i6 Q# _5 t4 }) p+ Q# U9 G

& m$ h! H! d4 d  R6 v0 w" Irvsb_wait_smbus_fi:$ f' X, ^8 A" E7 y+ _3 K3 O

' q0 @' `# m7 H( F& Fin al, dx
+ S8 @7 l* {/ X, C9 u

" B, q& j6 X9 J0 f* Hcall io_delay

7 x3 L+ h% B1 `. Z
8 O( @2 i' M( g1 N1 a2 ctest al, 01h
+ d* B! j  W" z" V9 t% z

4 _' z0 H# N5 r8 V' F8 l& ojnz rvsb_wait_smbus_fi
) ]. Y% F) v& J  `: L4 k

0 L; b# F; e% J" _% I
! m7 {0 d- ^) j  q;read data count
7 |  Z4 c8 Q  ?4 D+ |" m* R
2 J# C3 h& p+ n
mov dx,SMBUS_REG_BAR
4 G* R2 s, o% [2 q# Z% A, V
( z+ [+ j! F. o  C. Y
or dl,SMBUS_HDA0_REG

2 R( J4 b- Y1 o8 Q$ o3 U+ U8 }  f
in al,dx
0 n  P( l6 Q; T' h# o

. F: i& H  [/ g; U;read data from smbus block data

/ U7 a& u0 H( Q5 \
! }/ V. T( v9 hmov cl,14h

5 [- t/ I( c/ f- O7 J$ v2 i7 x: e! D7 I, _3 `% J
mov bx,offset REGSTR
4 o: b0 b% d& S; X# |$ v+ L1 C
rvsb_read_data:# {: h2 \9 }& Z4 }
9 \. }5 d' w; @- ~4 i( ]
mov dx,SMBUS_REG_BAR

: u  O7 }: H6 `4 Y# l; i) U+ n: `) U6 y; ?
or dl,SMBUS_BLKDA_REG

" |$ k' B. t9 \- @" k9 E9 `% ^1 Z; x3 h$ J9 b  U* _
in al,dx

; N. O' j& y8 m' ?
* L+ N* ]! B" B; acall hex2asc
- ]6 T( g) C) X' s7 X
1 i0 H1 \. A, I  B) Y+ m8 H: S9 T" V
dec cl
6 J( @) Z; N' _3 G$ {" q

) A  p9 G+ |8 K! finc bx
6 W2 S# f/ O/ y/ t

5 q0 C3 G  i/ w5 Y3 z1 y; Z4 Z" Vinc bx
* e! q. h6 V1 d7 C2 o2 w* i0 ]: e; a2 \! L8 {% h0 N
cmp cl,01h* v" G* E3 ^# h+ O4 h' x* f7 O9 n' |2 M
. C  z1 x$ D; g+ x
jae rvsb_read_data
5 N% H* I  T! E- M  a6 }
  u5 o9 |/ n1 {: B5 B& ^
pop ax
/ _1 l- ]. Y7 j$ F9 A  `

% f: ~5 s& K7 h4 T1 Q! ypop bx
  v! M$ m: B8 m6 t3 T
; Y% S( i( X9 d' Y) t& I
pop cx
2 d) n! c3 [/ {9 o2 w$ V

+ `, X8 }+ p2 y3 x% Spop dx$ c2 }3 |: d# a" v6 g7 V2 Z

9 `. E. _- {: ^8 \% V
ret) I1 C: u5 m' X. K1 Y4 t
read_via_smbus_block endp
: y0 L( h; o* O  j+ r, `' O  y7 A  K( F& w9 Q$ u- j& z2 D9 e
下图2演示ClockGen.exe运行时的状况:; ?; l. k, n2 F% p+ |) ?

9 H* y2 [2 ^+ l6 y) g cg2.JPG
6 d% K9 `/ J3 W0 c7 i& Z4 b4 t6 s              图2

8 g/ j+ a3 ?, e0 U7 ^ClockGen.asm只演示了VIA platforma + ICS9UM700的dump过程,至于其它的平台,有兴趣的朋友可以如法炮制。那么这只tool可不可以做成通用的呢?当然可以,只要从PCI configure space读出Vendor id识别出平台然后再根据具体的平台spec去获取smbus controller bar(可能要多看几份spec了J)然后就可以操作smbus了,clock generator slave address可以让用户输入(我看到的几个都是42h,但是也会有特例)。我比较懒,有兴趣的朋友可以试着完善它。最后依旧是开放完整的source code和可执行文件供有兴趣的朋友下载。9 Z0 }1 T. T6 {3 I, j' e- G

" B& p1 q+ {; `

6 Y4 g  M6 e- s0 X! n4 d: MEnjoy it!* h& X1 e$ U# A9 |

, ~2 }/ ^. [6 C3 u% C3 C$ s2 D- m/ q; n  ^
That’s all!4 b5 X0 i: U0 D! X$ _8 L

0 |  U& D' U1 }4 h; rPeter
( v! I: }( ]$ V
5 \: Y; X3 X7 ~  E, Y. k. |( C[ 本帖最后由 peterhu 于 2009-7-9 10:26 编辑 ]

ClockGen.rar

4.1 KB, 下载次数: 1342

回复

使用道具 举报

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

使用道具 举报

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

使用道具 举报

 楼主| 发表于 2009-7-10 21:21:19 | 显示全部楼层
Alexander 你功力深厚啊!
& h6 v' H" s! M呵呵...向您学习.
$ B0 h* C% }- G" [+ o+ H; ^+ R8 _5 z
/ H/ [  p2 G; U6 ]0 ~[ 本帖最后由 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, 下载次数: 1288

Hardware Editor

回复

使用道具 举报

发表于 2009-7-31 23:17:14 | 显示全部楼层
Faintsnow好样的~
- k/ r* ~0 U/ H: V+ Y3 W这个Tool实在是太棒了, 很好用哦~5 ^1 J  ]# a, e
我顶~~~~~~~
回复

使用道具 举报

发表于 2009-9-4 23:24:56 | 显示全部楼层
顶楼主。 ; a  O4 m+ E: c1 v4 h2 U
拜读啦,O(∩_∩)O~
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-10-18 07:59 , Processed in 0.088560 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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